Migrate to the AndroidX Shared Preferences.

- The version of the Shared Preferences bundled with the Android OS has been deprecated, similar to what has happened with other platform libraries. This is so that the libraries can be updated, regardless of the device's OS version.
This commit is contained in:
Severiano Jaramillo 2021-04-05 21:54:23 -07:00
parent 0bc607de03
commit 0166382b68
20 changed files with 134 additions and 115 deletions

View file

@ -62,8 +62,9 @@ android {
} }
dependencies { dependencies {
def lifecycle_version = "2.3.1"
def arch_version = "2.1.0" def arch_version = "2.1.0"
def lifecycle_version = "2.3.1"
def preference_version = "1.1.1"
def room_version = "2.2.6" def room_version = "2.2.6"
def rx_bindings_version = '3.0.0' def rx_bindings_version = '3.0.0'
def version_coroutine = '1.4.1' def version_coroutine = '1.4.1'
@ -75,6 +76,7 @@ dependencies {
// AndroidX // AndroidX
implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation "androidx.preference:preference-ktx:$preference_version"
// Google // Google
implementation 'com.google.zxing:core:3.4.0' implementation 'com.google.zxing:core:3.4.0'
implementation 'com.google.code.gson:gson:2.8.6' implementation 'com.google.code.gson:gson:2.8.6'

View file

@ -4,12 +4,13 @@ import android.content.pm.PackageManager
import android.os.AsyncTask import android.os.AsyncTask
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.preference.PreferenceManager
import android.util.Log import android.util.Log
import android.widget.Toast import android.widget.Toast
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.edit
import androidx.core.content.pm.PackageInfoCompat import androidx.core.content.pm.PackageInfoCompat
import androidx.preference.PreferenceManager
import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.crashlytics.FirebaseCrashlytics
import cy.agorise.bitsybitshareswallet.database.entities.Balance import cy.agorise.bitsybitshareswallet.database.entities.Balance
import cy.agorise.bitsybitshareswallet.database.entities.Transfer import cy.agorise.bitsybitshareswallet.database.entities.Transfer
@ -171,10 +172,9 @@ abstract class ConnectedActivity : AppCompatActivity() {
if (versionCode > 11 && !hasPurgedEquivalentValues) { if (versionCode > 11 && !hasPurgedEquivalentValues) {
thread { thread {
connectedActivityViewModel.purgeEquivalentValues() connectedActivityViewModel.purgeEquivalentValues()
PreferenceManager.getDefaultSharedPreferences(this) PreferenceManager.getDefaultSharedPreferences(this).edit {
.edit() putBoolean(Constants.KEY_HAS_PURGED_EQUIVALENT_VALUES, true)
.putBoolean(Constants.KEY_HAS_PURGED_EQUIVALENT_VALUES, true) }
.apply()
} }
} }
} }
@ -388,8 +388,9 @@ abstract class ConnectedActivity : AppCompatActivity() {
dateFormat.timeZone = TimeZone.getTimeZone("GMT") dateFormat.timeZone = TimeZone.getTimeZone("GMT")
try { try {
val date = dateFormat.parse(blockHeader.timestamp) dateFormat.parse(blockHeader.timestamp)?.let { date ->
transferViewModel.setBlockTime(blockNumber, date.time / 1000) transferViewModel.setBlockTime(blockNumber, date.time / 1000)
}
} catch (e: ParseException) { } catch (e: ParseException) {
Log.e(TAG, "ParseException. Msg: " + e.message) Log.e(TAG, "ParseException. Msg: " + e.message)
} }

View file

@ -2,7 +2,6 @@ package cy.agorise.bitsybitshareswallet.activities
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.preference.PreferenceManager
import android.util.Log import android.util.Log
import android.view.MenuItem import android.view.MenuItem
import androidx.navigation.findNavController import androidx.navigation.findNavController
@ -11,6 +10,7 @@ import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.onNavDestinationSelected import androidx.navigation.ui.onNavDestinationSelected
import androidx.navigation.ui.setupActionBarWithNavController import androidx.navigation.ui.setupActionBarWithNavController
import androidx.preference.PreferenceManager
import cy.agorise.bitsybitshareswallet.R import cy.agorise.bitsybitshareswallet.R
import cy.agorise.bitsybitshareswallet.databinding.ActivityMainBinding import cy.agorise.bitsybitshareswallet.databinding.ActivityMainBinding
import cy.agorise.bitsybitshareswallet.utils.Constants import cy.agorise.bitsybitshareswallet.utils.Constants
@ -36,6 +36,7 @@ class MainActivity : ConnectedActivity() {
) { ) {
setTheme(R.style.Theme_Bitsy_Dark) setTheme(R.style.Theme_Bitsy_Dark)
} }
binding = ActivityMainBinding.inflate(layoutInflater) binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)

View file

@ -1,7 +1,8 @@
package cy.agorise.bitsybitshareswallet.fragments package cy.agorise.bitsybitshareswallet.fragments
import android.preference.PreferenceManager import androidx.core.content.edit
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.preference.PreferenceManager
import cy.agorise.bitsybitshareswallet.R import cy.agorise.bitsybitshareswallet.R
import cy.agorise.bitsybitshareswallet.activities.ConnectedActivity import cy.agorise.bitsybitshareswallet.activities.ConnectedActivity
import cy.agorise.bitsybitshareswallet.database.entities.Authority import cy.agorise.bitsybitshareswallet.database.entities.Authority
@ -36,10 +37,11 @@ abstract class BaseAccountFragment : ConnectedFragment() {
val hashedPIN = CryptoUtils.createSHA256Hash(salt + pin) val hashedPIN = CryptoUtils.createSHA256Hash(salt + pin)
// Stores the user selected PIN, hashed // Stores the user selected PIN, hashed
PreferenceManager.getDefaultSharedPreferences(requireContext()).edit() PreferenceManager.getDefaultSharedPreferences(requireContext()).edit {
.putString(Constants.KEY_HASHED_PIN_PATTERN, hashedPIN) putString(Constants.KEY_HASHED_PIN_PATTERN, hashedPIN)
.putString(Constants.KEY_PIN_PATTERN_SALT, salt) putString(Constants.KEY_PIN_PATTERN_SALT, salt)
.putInt(Constants.KEY_SECURITY_LOCK_SELECTED, 1).apply() // 1 -> PIN putInt(Constants.KEY_SECURITY_LOCK_SELECTED, 1) // 1 -> PIN
}
// Stores the accounts this key refers to // Stores the accounts this key refers to
val id = accountProperties.id val id = accountProperties.id

View file

@ -2,11 +2,12 @@ package cy.agorise.bitsybitshareswallet.fragments
import android.os.Bundle import android.os.Bundle
import android.os.CountDownTimer import android.os.CountDownTimer
import android.preference.PreferenceManager
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.content.edit
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.preference.PreferenceManager
import cy.agorise.bitsybitshareswallet.R import cy.agorise.bitsybitshareswallet.R
import cy.agorise.bitsybitshareswallet.utils.Constants import cy.agorise.bitsybitshareswallet.utils.Constants
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
@ -118,10 +119,10 @@ abstract class BaseSecurityLockDialog : DialogFragment() {
incorrectSecurityLockTime = now incorrectSecurityLockTime = now
PreferenceManager.getDefaultSharedPreferences(context).edit() PreferenceManager.getDefaultSharedPreferences(context).edit {
.putInt(Constants.KEY_INCORRECT_SECURITY_LOCK_ATTEMPTS, ++incorrectSecurityLockAttempts) putInt(Constants.KEY_INCORRECT_SECURITY_LOCK_ATTEMPTS, ++incorrectSecurityLockAttempts)
.putLong(Constants.KEY_INCORRECT_SECURITY_LOCK_TIME, now) putLong(Constants.KEY_INCORRECT_SECURITY_LOCK_TIME, now)
.apply() }
} }
/** /**
@ -132,10 +133,10 @@ abstract class BaseSecurityLockDialog : DialogFragment() {
incorrectSecurityLockTime = 0 incorrectSecurityLockTime = 0
incorrectSecurityLockAttempts = 0 incorrectSecurityLockAttempts = 0
PreferenceManager.getDefaultSharedPreferences(context).edit() PreferenceManager.getDefaultSharedPreferences(context).edit {
.putInt(Constants.KEY_INCORRECT_SECURITY_LOCK_ATTEMPTS, incorrectSecurityLockAttempts) putInt(Constants.KEY_INCORRECT_SECURITY_LOCK_ATTEMPTS, incorrectSecurityLockAttempts)
.putLong(Constants.KEY_INCORRECT_SECURITY_LOCK_TIME, incorrectSecurityLockTime) putLong(Constants.KEY_INCORRECT_SECURITY_LOCK_TIME, incorrectSecurityLockTime)
.apply() }
} }
protected fun startContDownTimer() { protected fun startContDownTimer() {

View file

@ -5,15 +5,15 @@ import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.graphics.drawable.Animatable import android.graphics.drawable.Animatable
import android.os.Bundle import android.os.Bundle
import android.preference.PreferenceManager
import android.text.Html
import android.text.method.LinkMovementMethod import android.text.method.LinkMovementMethod
import android.view.* import android.view.*
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.os.ConfigurationCompat import androidx.core.os.ConfigurationCompat
import androidx.core.text.HtmlCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.navigation.fragment.navArgs import androidx.navigation.fragment.navArgs
import androidx.preference.PreferenceManager
import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.crashlytics.FirebaseCrashlytics
import cy.agorise.bitsybitshareswallet.R import cy.agorise.bitsybitshareswallet.R
import cy.agorise.bitsybitshareswallet.database.joins.TransferDetail import cy.agorise.bitsybitshareswallet.database.joins.TransferDetail
@ -130,12 +130,11 @@ class EReceiptFragment : Fragment() {
/** Formats the transfer TextView to show a link to explore the given transfer /** Formats the transfer TextView to show a link to explore the given transfer
* in a BitShares explorer */ * in a BitShares explorer */
private fun formatTransferTextView(transferId: String) { private fun formatTransferTextView(transferId: String) {
val tx = Html.fromHtml( val html = getString(
getString( R.string.template__tx,
R.string.template__tx, "<a href=\"http://bitshares-explorer.io/#/operations/$transferId\">$transferId</a>"
"<a href=\"http://bitshares-explorer.io/#/operations/$transferId\">$transferId</a>"
)
) )
val tx = HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY)
binding.tvTransferID.text = tx binding.tvTransferID.text = tx
binding.tvTransferID.movementMethod = LinkMovementMethod.getInstance() binding.tvTransferID.movementMethod = LinkMovementMethod.getInstance()
} }

View file

@ -1,7 +1,6 @@
package cy.agorise.bitsybitshareswallet.fragments package cy.agorise.bitsybitshareswallet.fragments
import android.os.Bundle import android.os.Bundle
import android.preference.PreferenceManager
import android.view.* import android.view.*
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
@ -13,6 +12,7 @@ import androidx.fragment.app.FragmentPagerAdapter
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.navigation.Navigation import androidx.navigation.Navigation
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.preference.PreferenceManager
import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.crashlytics.FirebaseCrashlytics
import cy.agorise.bitsybitshareswallet.R import cy.agorise.bitsybitshareswallet.R
import cy.agorise.bitsybitshareswallet.databinding.FragmentHomeBinding import cy.agorise.bitsybitshareswallet.databinding.FragmentHomeBinding
@ -135,7 +135,8 @@ class HomeFragment : Fragment() {
/** /**
* Pager adapter to create the placeholder fragments * Pager adapter to create the placeholder fragments
*/ */
private inner class PagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm) { private inner class PagerAdapter(fm: FragmentManager) :
FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
override fun getItem(position: Int): Fragment { override fun getItem(position: Int): Fragment {
// getItem is called to instantiate the fragment for the given page. // getItem is called to instantiate the fragment for the given page.

View file

@ -1,13 +1,14 @@
package cy.agorise.bitsybitshareswallet.fragments package cy.agorise.bitsybitshareswallet.fragments
import android.os.Bundle import android.os.Bundle
import android.preference.PreferenceManager
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.core.content.edit
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.preference.PreferenceManager
import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.crashlytics.FirebaseCrashlytics
import cy.agorise.bitsybitshareswallet.R import cy.agorise.bitsybitshareswallet.R
import cy.agorise.bitsybitshareswallet.databinding.FragmentLicenseBinding import cy.agorise.bitsybitshareswallet.databinding.FragmentLicenseBinding
@ -67,9 +68,9 @@ class LicenseFragment : Fragment() {
* sends the user to import/create account. * sends the user to import/create account.
*/ */
private fun agree() { private fun agree() {
PreferenceManager.getDefaultSharedPreferences(context).edit() PreferenceManager.getDefaultSharedPreferences(context).edit {
.putInt(Constants.KEY_LAST_AGREED_LICENSE_VERSION, Constants.CURRENT_LICENSE_VERSION) putInt(Constants.KEY_LAST_AGREED_LICENSE_VERSION, Constants.CURRENT_LICENSE_VERSION)
.apply() }
findNavController().navigate(R.id.import_brainkey_action) findNavController().navigate(R.id.import_brainkey_action)
} }

View file

@ -6,7 +6,6 @@ import android.content.pm.PackageManager
import android.database.Cursor import android.database.Cursor
import android.database.MatrixCursor import android.database.MatrixCursor
import android.os.Bundle import android.os.Bundle
import android.preference.PreferenceManager
import android.util.Log import android.util.Log
import android.view.* import android.view.*
import android.widget.PopupWindow import android.widget.PopupWindow
@ -19,6 +18,7 @@ import androidx.core.content.ContextCompat
import androidx.cursoradapter.widget.SimpleCursorAdapter import androidx.cursoradapter.widget.SimpleCursorAdapter
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.preference.PreferenceManager
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.customview.customView import com.afollestad.materialdialogs.customview.customView
import com.google.android.gms.maps.CameraUpdateFactory import com.google.android.gms.maps.CameraUpdateFactory
@ -549,7 +549,7 @@ class MerchantsFragment : Fragment(), OnMapReadyCallback, SearchView.OnSuggestio
try { try {
mMap?.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 100)) mMap?.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 100))
} catch (e: Exception) { } catch (e: Exception) {
Log.d(TAG, e.message) Log.d(TAG, e.message ?: "")
} }
} }
return true return true

View file

@ -1,12 +1,13 @@
package cy.agorise.bitsybitshareswallet.fragments package cy.agorise.bitsybitshareswallet.fragments
import android.os.Bundle import android.os.Bundle
import android.preference.PreferenceManager
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.WindowManager import android.view.WindowManager
import android.view.inputmethod.EditorInfo import android.view.inputmethod.EditorInfo
import androidx.core.content.edit
import androidx.preference.PreferenceManager
import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.jakewharton.rxbinding3.widget.textChanges import com.jakewharton.rxbinding3.widget.textChanges
import cy.agorise.bitsybitshareswallet.R import cy.agorise.bitsybitshareswallet.R
@ -100,10 +101,11 @@ class PINSecurityLockDialog : BaseSecurityLockDialog() {
val hashedPIN = CryptoUtils.createSHA256Hash(salt + pinConfirm) val hashedPIN = CryptoUtils.createSHA256Hash(salt + pinConfirm)
// Stores the newly selected PIN, hashed // Stores the newly selected PIN, hashed
PreferenceManager.getDefaultSharedPreferences(v.context).edit() PreferenceManager.getDefaultSharedPreferences(v.context).edit {
.putString(Constants.KEY_HASHED_PIN_PATTERN, hashedPIN) putString(Constants.KEY_HASHED_PIN_PATTERN, hashedPIN)
.putString(Constants.KEY_PIN_PATTERN_SALT, salt) putString(Constants.KEY_PIN_PATTERN_SALT, salt)
.putInt(Constants.KEY_SECURITY_LOCK_SELECTED, 1).apply() // 1 -> PIN putInt(Constants.KEY_SECURITY_LOCK_SELECTED, 1) // 1 -> PIN
}
dismiss() dismiss()
mCallback?.onPINPatternChanged() mCallback?.onPINPatternChanged()

View file

@ -1,10 +1,11 @@
package cy.agorise.bitsybitshareswallet.fragments package cy.agorise.bitsybitshareswallet.fragments
import android.os.Bundle import android.os.Bundle
import android.preference.PreferenceManager
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.content.edit
import androidx.preference.PreferenceManager
import com.andrognito.patternlockview.PatternLockView import com.andrognito.patternlockview.PatternLockView
import com.andrognito.patternlockview.listener.PatternLockViewListener import com.andrognito.patternlockview.listener.PatternLockViewListener
import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.crashlytics.FirebaseCrashlytics
@ -131,11 +132,11 @@ class PatternSecurityLockDialog : BaseSecurityLockDialog() {
val hashedPattern = CryptoUtils.createSHA256Hash(salt + patternConfirm) val hashedPattern = CryptoUtils.createSHA256Hash(salt + patternConfirm)
// Stores the newly selected Pattern, encrypted // Stores the newly selected Pattern, encrypted
PreferenceManager.getDefaultSharedPreferences(it).edit() PreferenceManager.getDefaultSharedPreferences(it).edit {
.putString(Constants.KEY_HASHED_PIN_PATTERN, hashedPattern) putString(Constants.KEY_HASHED_PIN_PATTERN, hashedPattern)
.putString(Constants.KEY_PIN_PATTERN_SALT, salt) putString(Constants.KEY_PIN_PATTERN_SALT, salt)
.putInt(Constants.KEY_SECURITY_LOCK_SELECTED, 2) putInt(Constants.KEY_SECURITY_LOCK_SELECTED, 2) // 2 -> Pattern
.apply() // 2 -> Pattern }
dismiss() dismiss()
mCallback?.onPINPatternChanged() mCallback?.onPINPatternChanged()

View file

@ -4,7 +4,6 @@ import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.graphics.drawable.Animatable import android.graphics.drawable.Animatable
import android.os.Bundle import android.os.Bundle
import android.preference.PreferenceManager
import android.util.Log import android.util.Log
import android.view.* import android.view.*
import android.widget.AdapterView import android.widget.AdapterView
@ -12,6 +11,7 @@ import androidx.appcompat.widget.Toolbar
import androidx.collection.LongSparseArray import androidx.collection.LongSparseArray
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.preference.PreferenceManager
import com.google.common.primitives.UnsignedLong import com.google.common.primitives.UnsignedLong
import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.jakewharton.rxbinding3.widget.textChanges import com.jakewharton.rxbinding3.widget.textChanges
@ -136,9 +136,7 @@ class ReceiveTransactionFragment : ConnectedFragment() {
) )
) )
mAssets.sortWith( mAssets.sortWith { a, b -> a.toString().compareTo(b.toString(), true) }
Comparator { a, b -> a.toString().compareTo(b.toString(), true) }
)
// Add an option at the end so the user can search for an asset other than the ones saved in the db // Add an option at the end so the user can search for an asset other than the ones saved in the db
val asset = cy.agorise.bitsybitshareswallet.database.entities.Asset( val asset = cy.agorise.bitsybitshareswallet.database.entities.Asset(
@ -208,7 +206,7 @@ class ReceiveTransactionFragment : ConnectedFragment() {
binding.actvAsset.textChanges() binding.actvAsset.textChanges()
.skipInitialValue() .skipInitialValue()
.debounce(500, TimeUnit.MILLISECONDS) .debounce(500, TimeUnit.MILLISECONDS)
.map { it.toString().trim().toUpperCase() } .map { it.toString().trim().toUpperCase(Locale.getDefault()) }
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe({ .subscribe({
if (!selectedInAutoCompleteTextView) { if (!selectedInAutoCompleteTextView) {

View file

@ -3,7 +3,6 @@ package cy.agorise.bitsybitshareswallet.fragments
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.preference.PreferenceManager
import android.provider.Settings import android.provider.Settings
import android.util.Log import android.util.Log
import android.view.* import android.view.*
@ -15,6 +14,7 @@ import androidx.core.content.ContextCompat
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs import androidx.navigation.fragment.navArgs
import androidx.preference.PreferenceManager
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.customview.customView import com.afollestad.materialdialogs.customview.customView
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
@ -52,7 +52,6 @@ import java.text.DecimalFormatSymbols
import java.util.ArrayList import java.util.ArrayList
import java.util.Locale import java.util.Locale
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import kotlin.Comparator
class SendTransactionFragment : ConnectedFragment(), ZXingScannerView.ResultHandler, class SendTransactionFragment : ConnectedFragment(), ZXingScannerView.ResultHandler,
BaseSecurityLockDialog.OnPINPatternEnteredListener { BaseSecurityLockDialog.OnPINPatternEnteredListener {
@ -186,9 +185,7 @@ class SendTransactionFragment : ConnectedFragment(), ZXingScannerView.ResultHand
balanceDetailViewModel.getAll().observe(viewLifecycleOwner, { balancesDetails -> balanceDetailViewModel.getAll().observe(viewLifecycleOwner, { balancesDetails ->
mBalancesDetails.clear() mBalancesDetails.clear()
mBalancesDetails.addAll(balancesDetails) mBalancesDetails.addAll(balancesDetails)
mBalancesDetails.sortWith( mBalancesDetails.sortWith { a, b -> a.toString().compareTo(b.toString(), true) }
Comparator { a, b -> a.toString().compareTo(b.toString(), true) }
)
mBalancesDetailsAdapter = BalancesDetailsAdapter( mBalancesDetailsAdapter = BalancesDetailsAdapter(
requireContext(), requireContext(),
android.R.layout.simple_spinner_item, android.R.layout.simple_spinner_item,
@ -461,9 +458,11 @@ class SendTransactionFragment : ConnectedFragment(), ZXingScannerView.ResultHand
// Try to select the invoice's Asset in the Assets spinner // Try to select the invoice's Asset in the Assets spinner
for (i in 0 until (mBalancesDetailsAdapter?.count ?: 0)) { for (i in 0 until (mBalancesDetailsAdapter?.count ?: 0)) {
if (mBalancesDetailsAdapter?.getItem(i)?.symbol == invoice.currency.toUpperCase() || if (mBalancesDetailsAdapter?.getItem(i)?.symbol == invoice.currency
.toUpperCase(Locale.getDefault()) ||
(invoice.currency.startsWith("bit", true) && (invoice.currency.startsWith("bit", true) &&
invoice.currency.replaceFirst("bit", "").toUpperCase() == invoice.currency.replaceFirst("bit", "")
.toUpperCase(Locale.getDefault()) ==
mBalancesDetailsAdapter?.getItem(i)?.symbol) mBalancesDetailsAdapter?.getItem(i)?.symbol)
) { ) {
binding.spAsset.setSelection(i) binding.spAsset.setSelection(i)
@ -477,7 +476,10 @@ class SendTransactionFragment : ConnectedFragment(), ZXingScannerView.ResultHand
if (balanceDetail == null) { if (balanceDetail == null) {
Snackbar.make( Snackbar.make(
binding.rootView, binding.rootView,
getString(R.string.error__you_dont_own_asset, invoice.currency.toUpperCase()), getString(
R.string.error__you_dont_own_asset,
invoice.currency.toUpperCase(Locale.getDefault())
),
Snackbar.LENGTH_INDEFINITE Snackbar.LENGTH_INDEFINITE
).setAction(android.R.string.ok) { }.show() ).setAction(android.R.string.ok) { }.show()
return return

View file

@ -3,15 +3,16 @@ package cy.agorise.bitsybitshareswallet.fragments
import android.content.Context import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.preference.PreferenceManager
import android.util.Log import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.collection.LongSparseArray import androidx.collection.LongSparseArray
import androidx.core.content.edit
import androidx.core.content.res.ResourcesCompat import androidx.core.content.res.ResourcesCompat
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.callbacks.onDismiss import com.afollestad.materialdialogs.callbacks.onDismiss
@ -485,9 +486,9 @@ class SettingsFragment : ConnectedFragment(), BaseSecurityLockDialog.OnPINPatter
when (index) { when (index) {
0 -> { /* None */ 0 -> { /* None */
PreferenceManager.getDefaultSharedPreferences(context).edit() PreferenceManager.getDefaultSharedPreferences(context).edit {
.putInt(Constants.KEY_SECURITY_LOCK_SELECTED, 0) putInt(Constants.KEY_SECURITY_LOCK_SELECTED, 0) // 0 -> None
.apply() // 0 -> None }
// Call this function to update the UI // Call this function to update the UI
onPINPatternChanged() onPINPatternChanged()
@ -564,8 +565,9 @@ class SettingsFragment : ConnectedFragment(), BaseSecurityLockDialog.OnPINPatter
.cancelable(false) .cancelable(false)
.positiveButton(R.string.button__copied) { .positiveButton(R.string.button__copied) {
val now = System.currentTimeMillis() val now = System.currentTimeMillis()
PreferenceManager.getDefaultSharedPreferences(it.context).edit() PreferenceManager.getDefaultSharedPreferences(it.context).edit {
.putLong(Constants.KEY_LAST_ACCOUNT_BACKUP, now).apply() putLong(Constants.KEY_LAST_ACCOUNT_BACKUP, now)
}
binding.tvBackupWarning.visibility = View.GONE binding.tvBackupWarning.visibility = View.GONE
} }
@ -623,14 +625,12 @@ class SettingsFragment : ConnectedFragment(), BaseSecurityLockDialog.OnPINPatter
// Clears the database. // Clears the database.
viewModel.clearDatabase(context) viewModel.clearDatabase(context)
// Clears the shared preferences. val pref = PreferenceManager.getDefaultSharedPreferences(context).edit {
val pref = PreferenceManager.getDefaultSharedPreferences(context) // Clears the shared preferences.
pref.edit().clear().apply() clear()
// Marks the license as agreed, so that it is not shown to the user again.
// Marks the license as agreed, so that it is not shown to the user again. putInt(Constants.KEY_LAST_AGREED_LICENSE_VERSION, Constants.CURRENT_LICENSE_VERSION)
pref.edit().putInt( }
Constants.KEY_LAST_AGREED_LICENSE_VERSION, Constants.CURRENT_LICENSE_VERSION
).apply()
// Restarts the activity, which will restart the whole application since it uses a // Restarts the activity, which will restart the whole application since it uses a
// single activity architecture. // single activity architecture.
@ -639,4 +639,3 @@ class SettingsFragment : ConnectedFragment(), BaseSecurityLockDialog.OnPINPatter
activity?.startActivity(intent) activity?.startActivity(intent)
} }
} }

View file

@ -5,13 +5,13 @@ import android.content.pm.PackageManager
import android.graphics.Point import android.graphics.Point
import android.os.Bundle import android.os.Bundle
import android.os.Environment import android.os.Environment
import android.preference.PreferenceManager
import android.view.* import android.view.*
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.list.listItemsMultiChoice import com.afollestad.materialdialogs.list.listItemsMultiChoice
@ -26,6 +26,7 @@ import cy.agorise.bitsybitshareswallet.viewmodels.TransactionsViewModel
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import java.io.File import java.io.File
import java.util.*
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
/** /**
@ -110,7 +111,7 @@ class TransactionsFragment : Fragment(), FilterOptionsDialog.OnFilterOptionsSele
searchView.queryTextChangeEvents() searchView.queryTextChangeEvents()
.skipInitialValue() .skipInitialValue()
.debounce(500, TimeUnit.MILLISECONDS) .debounce(500, TimeUnit.MILLISECONDS)
.map { it.queryText.toString().toLowerCase() } .map { it.queryText.toString().toLowerCase(Locale.getDefault()) }
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe { .subscribe {
viewModel.setFilterQuery(it) viewModel.setFilterQuery(it)

View file

@ -1,8 +1,8 @@
package cy.agorise.bitsybitshareswallet.processors package cy.agorise.bitsybitshareswallet.processors
import android.content.Context import android.content.Context
import android.preference.PreferenceManager
import android.util.Log import android.util.Log
import androidx.preference.PreferenceManager
import cy.agorise.bitsybitshareswallet.database.entities.Transfer import cy.agorise.bitsybitshareswallet.database.entities.Transfer
import cy.agorise.bitsybitshareswallet.models.HistoricalOperationEntry import cy.agorise.bitsybitshareswallet.models.HistoricalOperationEntry
import cy.agorise.bitsybitshareswallet.repositories.AuthorityRepository import cy.agorise.bitsybitshareswallet.repositories.AuthorityRepository
@ -75,8 +75,8 @@ class TransfersLoader(private var mContext: Context?) {
transferRepository = TransferRepository(mContext!!) transferRepository = TransferRepository(mContext!!)
authorityRepository = AuthorityRepository(mContext!!) authorityRepository = AuthorityRepository(mContext!!)
val pref = PreferenceManager.getDefaultSharedPreferences(mContext) val userId = PreferenceManager.getDefaultSharedPreferences(mContext)
val userId = pref.getString(Constants.KEY_CURRENT_ACCOUNT_ID, "") ?: "" .getString(Constants.KEY_CURRENT_ACCOUNT_ID, "") ?: ""
if (userId != "") { if (userId != "") {
mCurrentAccount = UserAccount(userId) mCurrentAccount = UserAccount(userId)
mDisposables.add( mDisposables.add(

View file

@ -2,9 +2,10 @@ package cy.agorise.bitsybitshareswallet.repositories
import android.content.Context import android.content.Context
import android.os.AsyncTask import android.os.AsyncTask
import android.preference.PreferenceManager
import android.util.Log import android.util.Log
import androidx.core.content.edit
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.preference.PreferenceManager
import cy.agorise.bitsybitshareswallet.database.BitsyDatabase import cy.agorise.bitsybitshareswallet.database.BitsyDatabase
import cy.agorise.bitsybitshareswallet.database.daos.MerchantDao import cy.agorise.bitsybitshareswallet.database.daos.MerchantDao
import cy.agorise.bitsybitshareswallet.database.entities.Merchant import cy.agorise.bitsybitshareswallet.database.entities.Merchant
@ -41,7 +42,7 @@ class MerchantRepository internal constructor(val context: Context) : retrofit2.
.addConverterFactory(GsonConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create())
.build() .build()
bitsyWebservice = retrofit.create<BitsyWebservice>(BitsyWebservice::class.java) bitsyWebservice = retrofit.create(BitsyWebservice::class.java)
} }
/** Returns a LiveData object directly from the database while the response from the WebService is obtained. */ /** Returns a LiveData object directly from the database while the response from the WebService is obtained. */
@ -79,8 +80,9 @@ class MerchantRepository internal constructor(val context: Context) : retrofit2.
updateMerchants(merchantsList) updateMerchants(merchantsList)
val now = System.currentTimeMillis() val now = System.currentTimeMillis()
PreferenceManager.getDefaultSharedPreferences(context).edit() PreferenceManager.getDefaultSharedPreferences(context).edit {
.putLong(Constants.KEY_MERCHANTS_LAST_UPDATE, now).apply() putLong(Constants.KEY_MERCHANTS_LAST_UPDATE, now)
}
} }
} }
} }

View file

@ -2,9 +2,10 @@ package cy.agorise.bitsybitshareswallet.repositories
import android.content.Context import android.content.Context
import android.os.AsyncTask import android.os.AsyncTask
import android.preference.PreferenceManager
import android.util.Log import android.util.Log
import androidx.core.content.edit
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.preference.PreferenceManager
import cy.agorise.bitsybitshareswallet.database.BitsyDatabase import cy.agorise.bitsybitshareswallet.database.BitsyDatabase
import cy.agorise.bitsybitshareswallet.database.daos.TellerDao import cy.agorise.bitsybitshareswallet.database.daos.TellerDao
import cy.agorise.bitsybitshareswallet.database.entities.Teller import cy.agorise.bitsybitshareswallet.database.entities.Teller
@ -79,8 +80,9 @@ class TellerRepository internal constructor(val context: Context) : retrofit2.Ca
updateTellers(tellersList) updateTellers(tellersList)
val now = System.currentTimeMillis() val now = System.currentTimeMillis()
PreferenceManager.getDefaultSharedPreferences(context).edit() PreferenceManager.getDefaultSharedPreferences(context).edit {
.putLong(Constants.KEY_TELLERS_LAST_UPDATE, now).apply() putLong(Constants.KEY_TELLERS_LAST_UPDATE, now).apply()
}
} }
} }
} }

View file

@ -1,9 +1,7 @@
package cy.agorise.bitsybitshareswallet.repositories package cy.agorise.bitsybitshareswallet.repositories
import android.content.Context import android.content.Context
import android.content.SharedPreferences
import android.os.AsyncTask import android.os.AsyncTask
import android.preference.PreferenceManager
import android.util.Log import android.util.Log
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import cy.agorise.bitsybitshareswallet.database.BitsyDatabase import cy.agorise.bitsybitshareswallet.database.BitsyDatabase
@ -27,20 +25,18 @@ class TransferRepository internal constructor(context: Context) {
private val mTransferDao: TransferDao private val mTransferDao: TransferDao
private val mEquivalentValuesDao: EquivalentValueDao private val mEquivalentValuesDao: EquivalentValueDao
private val compositeDisposable = CompositeDisposable() private val compositeDisposable = CompositeDisposable()
private val mPreferences: SharedPreferences
init { init {
val db = BitsyDatabase.getDatabase(context) val db = BitsyDatabase.getDatabase(context)
mTransferDao = db!!.transferDao() mTransferDao = db!!.transferDao()
mEquivalentValuesDao = db.equivalentValueDao() mEquivalentValuesDao = db.equivalentValueDao()
mPreferences = PreferenceManager.getDefaultSharedPreferences(context)
} }
fun insertAll(transfers: List<Transfer>) { fun insertAll(transfers: List<Transfer>) {
insertAllAsyncTask(mTransferDao).execute(transfers) insertAllAsyncTask(mTransferDao).execute(transfers)
} }
fun update(transfer: Transfer){ fun update(transfer: Transfer) {
mTransferDao.insert(transfer) mTransferDao.insert(transfer)
} }
@ -82,11 +78,17 @@ class TransferRepository internal constructor(context: Context) {
compositeDisposable.add(mTransferDao.getTransfersWithMissingValueIn(symbol) compositeDisposable.add(mTransferDao.getTransfersWithMissingValueIn(symbol)
.map { transfer -> obtainFiatValue(transfer, symbol) } .map { transfer -> obtainFiatValue(transfer, symbol) }
.subscribe({ .subscribe({
if(it.value >= 0) mEquivalentValuesDao.insert(it) if (it.value >= 0) mEquivalentValuesDao.insert(it)
},{ }, {
Log.e(TAG,"Error while trying to create a new equivalent value. Msg: ${it.message}") Log.e(
for(element in it.stackTrace){ TAG,
Log.e(TAG,"${element.className}#${element.methodName}:${element.lineNumber}") "Error while trying to create a new equivalent value. Msg: ${it.message}"
)
for (element in it.stackTrace) {
Log.e(
TAG,
"${element.className}#${element.methodName}:${element.lineNumber}"
)
} }
}) })
) )
@ -107,20 +109,23 @@ class TransferRepository internal constructor(context: Context) {
val dateFormat = SimpleDateFormat("dd-MM-yyyy", Locale.ROOT) val dateFormat = SimpleDateFormat("dd-MM-yyyy", Locale.ROOT)
val date = Date(transfer.timestamp * 1000) val date = Date(transfer.timestamp * 1000)
val response = sg.getService(CoingeckoService::class.java) val response = sg.getService(CoingeckoService::class.java)
?.getHistoricalValueSync("bitshares", dateFormat.format(date), false) ?.getHistoricalValueSync("bitshares", dateFormat.format(date), false)
?.execute() ?.execute()
var equivalentFiatValue = -1L var equivalentFiatValue = -1L
if(response?.isSuccessful == true){ if (response?.isSuccessful == true) {
val price: Double = response.body()?.market_data?.current_price?.get(symbol.toLowerCase()) ?: -1.0 val price: Double = response.body()?.market_data?.current_price
if(price > 0){ ?.get(symbol.toLowerCase(Locale.getDefault())) ?: -1.0
if (price > 0) {
// The equivalent value is obtained by: // The equivalent value is obtained by:
// 1- Dividing the base value by 100000 (BTS native precision) // 1- Dividing the base value by 100000 (BTS native precision)
// 2- Multiplying that BTS value by the unit price in the chosen fiat // 2- Multiplying that BTS value by the unit price in the chosen fiat
// 3- Multiplying the resulting value by 100 in order to express it in cents // 3- Multiplying the resulting value by 100 in order to express it in cents
equivalentFiatValue = Math.round(transfer.btsValue?.toFloat()?.div(1e5)?.times(price)?.times(100) ?: -1.0) equivalentFiatValue = Math.round(
transfer.btsValue?.toFloat()?.div(1e5)?.times(price)?.times(100) ?: -1.0
)
} }
}else{ } else {
Log.w(TAG,"Request was not successful. code: ${response?.code()}") Log.w(TAG, "Request was not successful. code: ${response?.code()}")
} }
return EquivalentValue(transfer.id, equivalentFiatValue, symbol) return EquivalentValue(transfer.id, equivalentFiatValue, symbol)
} }
@ -160,7 +165,7 @@ class TransferRepository internal constructor(context: Context) {
* be cleared. * be cleared.
*/ */
fun onCleared() { fun onCleared() {
if(!compositeDisposable.isDisposed) if (!compositeDisposable.isDisposed)
compositeDisposable.clear() compositeDisposable.clear()
} }
} }

View file

@ -1,8 +1,9 @@
package cy.agorise.bitsybitshareswallet.utils package cy.agorise.bitsybitshareswallet.utils
import android.content.Context import android.content.Context
import android.preference.PreferenceManager
import android.util.Base64 import android.util.Base64
import androidx.core.content.edit
import androidx.preference.PreferenceManager
import com.moldedbits.r2d2.R2d2 import com.moldedbits.r2d2.R2d2
import java.security.MessageDigest import java.security.MessageDigest
@ -32,11 +33,9 @@ object CryptoUtils {
fun put(context: Context, key: String, value: String) { fun put(context: Context, key: String, value: String) {
val r2d2 = R2d2(context) val r2d2 = R2d2(context)
val encrypted = r2d2.encryptData(value) val encrypted = r2d2.encryptData(value)
PreferenceManager PreferenceManager.getDefaultSharedPreferences(context).edit {
.getDefaultSharedPreferences(context) putString(key, encrypted)
.edit() }
.putString(key, encrypted)
.apply()
} }
/** /**