Create method to always observe the database for Missing transaction times, which automatically launches a call to the NetworkService to obtain such value from the corresponding transfer's blockNumber. This value is updated in the Database and shown in the corresponding transaction item in the Transactions screen automatically.

This commit is contained in:
Severiano Jaramillo 2018-12-23 14:11:26 -06:00
parent 7fb1d4ff86
commit 962afe78c6
5 changed files with 108 additions and 8 deletions

View file

@ -18,6 +18,7 @@ import cy.agorise.bitsybitshareswallet.processors.TransfersLoader
import cy.agorise.bitsybitshareswallet.repositories.AssetRepository import cy.agorise.bitsybitshareswallet.repositories.AssetRepository
import cy.agorise.bitsybitshareswallet.utils.Constants import cy.agorise.bitsybitshareswallet.utils.Constants
import cy.agorise.bitsybitshareswallet.viewmodels.BalanceViewModel import cy.agorise.bitsybitshareswallet.viewmodels.BalanceViewModel
import cy.agorise.bitsybitshareswallet.viewmodels.TransferViewModel
import cy.agorise.bitsybitshareswallet.viewmodels.UserAccountViewModel import cy.agorise.bitsybitshareswallet.viewmodels.UserAccountViewModel
import cy.agorise.graphenej.Asset import cy.agorise.graphenej.Asset
import cy.agorise.graphenej.AssetAmount import cy.agorise.graphenej.AssetAmount
@ -27,12 +28,16 @@ import cy.agorise.graphenej.api.android.NetworkService
import cy.agorise.graphenej.api.android.RxBus import cy.agorise.graphenej.api.android.RxBus
import cy.agorise.graphenej.api.calls.* import cy.agorise.graphenej.api.calls.*
import cy.agorise.graphenej.models.AccountProperties import cy.agorise.graphenej.models.AccountProperties
import cy.agorise.graphenej.models.BlockHeader
import cy.agorise.graphenej.models.FullAccountDetails import cy.agorise.graphenej.models.FullAccountDetails
import cy.agorise.graphenej.models.JsonRpcResponse import cy.agorise.graphenej.models.JsonRpcResponse
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposable
import java.util.HashMap import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
import kotlin.collections.HashMap
/** /**
* Class in charge of managing the connection to graphenej's NetworkService * Class in charge of managing the connection to graphenej's NetworkService
@ -44,9 +49,11 @@ abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection {
private val RESPONSE_GET_ACCOUNTS = 2 private val RESPONSE_GET_ACCOUNTS = 2
private val RESPONSE_GET_ACCOUNT_BALANCES = 3 private val RESPONSE_GET_ACCOUNT_BALANCES = 3
private val RESPONSE_GET_ASSETS = 4 private val RESPONSE_GET_ASSETS = 4
private val RESPONSE_GET_BLOCK_HEADER = 5
private lateinit var mUserAccountViewModel: UserAccountViewModel private lateinit var mUserAccountViewModel: UserAccountViewModel
private lateinit var mBalanceViewModel: BalanceViewModel private lateinit var mBalanceViewModel: BalanceViewModel
private lateinit var mTransferViewModel: TransferViewModel
private lateinit var mAssetRepository: AssetRepository private lateinit var mAssetRepository: AssetRepository
@ -69,6 +76,11 @@ abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection {
// Map used to keep track of request and response id pairs // Map used to keep track of request and response id pairs
private val responseMap = HashMap<Long, Int>() private val responseMap = HashMap<Long, Int>()
/** Map used to keep track of request id and block number pairs */
private val requestIdToBlockNumberMap = HashMap<Long, Long>()
private var blockNumberWithMissingTime = 0L
/** /**
* Flag used to keep track of the NetworkService binding state * Flag used to keep track of the NetworkService binding state
*/ */
@ -110,6 +122,17 @@ abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection {
} }
}) })
//Configure TransferViewModel to obtain the Transfer's block numbers with missing time information, one by one
mTransferViewModel = ViewModelProviders.of(this).get(TransferViewModel::class.java)
mTransferViewModel.getTransferBlockNumberWithMissingTime().observe(this, Observer<Long>{ blockNumber ->
if (blockNumber != null && blockNumber != blockNumberWithMissingTime) {
blockNumberWithMissingTime = blockNumber
Log.d(TAG, "Block number: $blockNumber, Time: ${System.currentTimeMillis()}")
mHandler.postDelayed(mRequestBlockMissingTimeTask, 10)
}
})
mDisposable = RxBus.getBusInstance() mDisposable = RxBus.getBusInstance()
.asFlowable() .asFlowable()
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
@ -136,6 +159,12 @@ abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection {
RESPONSE_GET_ASSETS -> RESPONSE_GET_ASSETS ->
handleAssets(message.result as List<Asset>) handleAssets(message.result as List<Asset>)
RESPONSE_GET_BLOCK_HEADER -> {
val blockNumber = requestIdToBlockNumberMap[message.id] ?: 0L
handleBlockHeader(message.result as BlockHeader, blockNumber)
requestIdToBlockNumberMap.remove(message.id)
}
} }
responseMap.remove(message.id) responseMap.remove(message.id)
} }
@ -245,6 +274,22 @@ abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection {
missingAssets.clear() missingAssets.clear()
} }
/**
* Receives the [BlockHeader] related to a Transfer's missing time and saves it into the database.
*/
private fun handleBlockHeader(blockHeader: BlockHeader, blockNumber: Long) {
val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US)
dateFormat.timeZone = TimeZone.getTimeZone("GMT")
try {
val date = dateFormat.parse(blockHeader.timestamp)
mTransferViewModel.setBlockTime(blockNumber, date.time / 1000)
} catch (e: ParseException) {
Log.e(TAG, "ParseException. Msg: " + e.message)
}
}
private fun updateBalances() { private fun updateBalances() {
if (mNetworkService!!.isConnected) { if (mNetworkService!!.isConnected) {
val id = mNetworkService!!.sendMessage(GetAccountBalances(mCurrentAccount, ArrayList()), val id = mNetworkService!!.sendMessage(GetAccountBalances(mCurrentAccount, ArrayList()),
@ -299,11 +344,28 @@ abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection {
responseMap[id] = RESPONSE_GET_FULL_ACCOUNTS responseMap[id] = RESPONSE_GET_FULL_ACCOUNTS
} }
} else { } else {
Log.w(TAG, "NetworkService is null or is not connected. mNetworkService: $mNetworkService")
}
mHandler.postDelayed(this, Constants.MISSING_PAYMENT_CHECK_PERIOD) mHandler.postDelayed(this, Constants.MISSING_PAYMENT_CHECK_PERIOD)
} }
} }
}
/**
* Task used to obtain the missing time from a block from Graphenej's NetworkService.
*/
private val mRequestBlockMissingTimeTask = object : Runnable {
override fun run() {
if (mNetworkService != null && mNetworkService!!.isConnected) {
val id = mNetworkService!!.sendMessage(GetBlockHeader(blockNumberWithMissingTime),
GetBlockHeader.REQUIRED_API)
responseMap[id] = RESPONSE_GET_BLOCK_HEADER
requestIdToBlockNumberMap[id] = blockNumberWithMissingTime
} else {
mHandler.postDelayed(this, Constants.MISSING_PAYMENT_CHECK_PERIOD)
}
}
}
override fun onServiceConnected(name: ComponentName?, service: IBinder?) { override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
// We've bound to LocalService, cast the IBinder and get LocalService instance // We've bound to LocalService, cast the IBinder and get LocalService instance

View file

@ -17,12 +17,18 @@ interface TransferDao {
@Insert(onConflict = OnConflictStrategy.IGNORE) @Insert(onConflict = OnConflictStrategy.IGNORE)
fun insertAll(transfers: List<Transfer>) fun insertAll(transfers: List<Transfer>)
@Query("SELECT COUNT(*) FROM transfers") @Query("UPDATE transfers SET timestamp=:timestamp WHERE block_number=:blockNumber")
fun getCount(): Single<Int> fun setBlockTime(blockNumber: Long, timestamp: Long)
@Query("SELECT * FROM transfers") @Query("SELECT * FROM transfers")
fun getAll(): LiveData<List<Transfer>> fun getAll(): LiveData<List<Transfer>>
@Query("SELECT COUNT(*) FROM transfers")
fun getCount(): Single<Int>
@Query("SELECT block_number FROM transfers WHERE timestamp='0' LIMIT 1")
fun getTransferBlockNumberWithMissingTime(): LiveData<Long>
@Query("DELETE FROM transfers") @Query("DELETE FROM transfers")
fun deleteAll() fun deleteAll()
} }

View file

@ -7,9 +7,6 @@ import android.content.ServiceConnection
import android.os.IBinder import android.os.IBinder
import android.preference.PreferenceManager import android.preference.PreferenceManager
import android.util.Log import android.util.Log
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
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

View file

@ -21,6 +21,10 @@ class TransferRepository internal constructor(context: Context) {
insertAllAsyncTask(mTransferDao).execute(transfers) insertAllAsyncTask(mTransferDao).execute(transfers)
} }
fun setBlockTime(blockNumber: Long, timestamp: Long) {
setBlockTimeAsyncTask(mTransferDao).execute(Pair(blockNumber, timestamp))
}
fun getAll(): LiveData<List<Transfer>> { fun getAll(): LiveData<List<Transfer>> {
return mTransferDao.getAll() return mTransferDao.getAll()
} }
@ -29,6 +33,10 @@ class TransferRepository internal constructor(context: Context) {
return mTransferDao.getCount() return mTransferDao.getCount()
} }
fun getTransferBlockNumberWithMissingTime(): LiveData<Long> {
return mTransferDao.getTransferBlockNumberWithMissingTime()
}
fun deleteAll() { fun deleteAll() {
deleteAllAsyncTask(mTransferDao).execute() deleteAllAsyncTask(mTransferDao).execute()
} }
@ -42,6 +50,15 @@ class TransferRepository internal constructor(context: Context) {
} }
} }
private class setBlockTimeAsyncTask internal constructor(private val mAsyncTaskDao: TransferDao) :
AsyncTask<Pair<Long, Long>, Void, Void>() {
override fun doInBackground(vararg pair: Pair<Long, Long>): Void? {
mAsyncTaskDao.setBlockTime(pair[0].first, pair[0].second)
return null
}
}
private class deleteAllAsyncTask internal constructor(private val mAsyncTaskDao: TransferDao) : private class deleteAllAsyncTask internal constructor(private val mAsyncTaskDao: TransferDao) :
AsyncTask<Void, Void, Void>() { AsyncTask<Void, Void, Void>() {

View file

@ -0,0 +1,18 @@
package cy.agorise.bitsybitshareswallet.viewmodels
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import cy.agorise.bitsybitshareswallet.repositories.TransferRepository
class TransferViewModel(application: Application) : AndroidViewModel(application) {
private var mRepository = TransferRepository(application)
internal fun setBlockTime(blockNumber: Long, timestamp: Long) {
mRepository.setBlockTime(blockNumber, timestamp)
}
internal fun getTransferBlockNumberWithMissingTime(): LiveData<Long> {
return mRepository.getTransferBlockNumberWithMissingTime()
}
}