Migrate to the new graphenej version.
- Migrated the whole app to the new graphenej version, which removes the usage of the Android Service, enabling to aim for a better and simpler architecture. - Did a good number of modifications to keep the same or better functionality in all parts of the app that use the NetworkService.
This commit is contained in:
parent
b5411fa7fc
commit
766d42386a
9 changed files with 148 additions and 167 deletions
|
@ -1,14 +1,9 @@
|
||||||
package cy.agorise.bitsybitshareswallet.activities
|
package cy.agorise.bitsybitshareswallet.activities
|
||||||
|
|
||||||
import android.content.ComponentName
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.content.ServiceConnection
|
|
||||||
import android.content.pm.PackageManager
|
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.os.IBinder
|
|
||||||
import android.preference.PreferenceManager
|
import android.preference.PreferenceManager
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
@ -56,7 +51,7 @@ import kotlin.concurrent.thread
|
||||||
* This class manages everything related to keeping the information in the database updated using graphenej's
|
* This class manages everything related to keeping the information in the database updated using graphenej's
|
||||||
* NetworkService, leaving to MainActivity only the Navigation work and some other UI features.
|
* NetworkService, leaving to MainActivity only the Navigation work and some other UI features.
|
||||||
*/
|
*/
|
||||||
abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection {
|
abstract class ConnectedActivity : AppCompatActivity() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "ConnectedActivity"
|
private const val TAG = "ConnectedActivity"
|
||||||
|
@ -96,7 +91,7 @@ abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection {
|
||||||
private var missingAssets = ArrayList<Asset>()
|
private var missingAssets = ArrayList<Asset>()
|
||||||
|
|
||||||
/* Network service connection */
|
/* Network service connection */
|
||||||
protected var mNetworkService: NetworkService? = null
|
protected var mNetworkService: NetworkService? = NetworkService.getInstance()
|
||||||
|
|
||||||
// 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>()
|
||||||
|
@ -110,11 +105,6 @@ abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection {
|
||||||
// to resolve an equivalent BTS value
|
// to resolve an equivalent BTS value
|
||||||
var transfer: Transfer? = null
|
var transfer: Transfer? = null
|
||||||
|
|
||||||
/**
|
|
||||||
* Flag used to keep track of the NetworkService binding state
|
|
||||||
*/
|
|
||||||
private var mShouldUnbindNetwork: Boolean = false
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
@ -227,8 +217,7 @@ abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection {
|
||||||
|
|
||||||
if (message.error == null) {
|
if (message.error == null) {
|
||||||
if (responseMap.containsKey(message.id)) {
|
if (responseMap.containsKey(message.id)) {
|
||||||
val responseType = responseMap[message.id]
|
when (responseMap[message.id]) {
|
||||||
when (responseType) {
|
|
||||||
RESPONSE_GET_FULL_ACCOUNTS ->
|
RESPONSE_GET_FULL_ACCOUNTS ->
|
||||||
handleAccountDetails((message.result as List<*>)[0] as FullAccountDetails)
|
handleAccountDetails((message.result as List<*>)[0] as FullAccountDetails)
|
||||||
|
|
||||||
|
@ -522,23 +511,9 @@ abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
|
|
||||||
// We've bound to LocalService, cast the IBinder and get LocalService instance
|
|
||||||
val binder = service as NetworkService.LocalBinder
|
|
||||||
mNetworkService = binder.service
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onServiceDisconnected(name: ComponentName?) { }
|
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
||||||
val intent = Intent(this, NetworkService::class.java)
|
|
||||||
if (bindService(intent, this, Context.BIND_AUTO_CREATE)) {
|
|
||||||
mShouldUnbindNetwork = true
|
|
||||||
} else {
|
|
||||||
Log.e(TAG, "Binding to the network service failed.")
|
|
||||||
}
|
|
||||||
mHandler.postDelayed(mCheckMissingPaymentsTask, Constants.MISSING_PAYMENT_CHECK_PERIOD)
|
mHandler.postDelayed(mCheckMissingPaymentsTask, Constants.MISSING_PAYMENT_CHECK_PERIOD)
|
||||||
mHandler.postDelayed(verifyConnectionToSuitableNodeTask, NODE_CHECK_DELAY)
|
mHandler.postDelayed(verifyConnectionToSuitableNodeTask, NODE_CHECK_DELAY)
|
||||||
}
|
}
|
||||||
|
@ -549,12 +524,6 @@ abstract class ConnectedActivity : AppCompatActivity(), ServiceConnection {
|
||||||
mConnectedActivityViewModel.updateNodeLatencies(nodes as List<FullNode>)
|
mConnectedActivityViewModel.updateNodeLatencies(nodes as List<FullNode>)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unbinding from network service
|
|
||||||
if (mShouldUnbindNetwork) {
|
|
||||||
unbindService(this)
|
|
||||||
mShouldUnbindNetwork = false
|
|
||||||
mNetworkService = null
|
|
||||||
}
|
|
||||||
mHandler.removeCallbacks(mCheckMissingPaymentsTask)
|
mHandler.removeCallbacks(mCheckMissingPaymentsTask)
|
||||||
mHandler.removeCallbacks(mRequestMissingUserAccountsTask)
|
mHandler.removeCallbacks(mRequestMissingUserAccountsTask)
|
||||||
mHandler.removeCallbacks(mRequestMissingAssetsTask)
|
mHandler.removeCallbacks(mRequestMissingAssetsTask)
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
package cy.agorise.bitsybitshareswallet.fragments
|
package cy.agorise.bitsybitshareswallet.fragments
|
||||||
|
|
||||||
import android.content.ComponentName
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.content.ServiceConnection
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.IBinder
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.core.os.ConfigurationCompat
|
import androidx.core.os.ConfigurationCompat
|
||||||
|
@ -23,17 +18,14 @@ import io.reactivex.disposables.CompositeDisposable
|
||||||
* Base fragment that defines the methods and variables commonly used in all fragments that directly connect and
|
* Base fragment that defines the methods and variables commonly used in all fragments that directly connect and
|
||||||
* talk to the BitShares nodes through graphenej's NetworkService
|
* talk to the BitShares nodes through graphenej's NetworkService
|
||||||
*/
|
*/
|
||||||
abstract class ConnectedFragment : Fragment(), ServiceConnection {
|
abstract class ConnectedFragment : Fragment() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "ConnectedFragment"
|
private const val TAG = "ConnectedFragment"
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Network service connection */
|
/** Network service connection */
|
||||||
protected var mNetworkService: NetworkService? = null
|
protected var mNetworkService: NetworkService? = NetworkService.getInstance()
|
||||||
|
|
||||||
/** Flag used to keep track of the NetworkService binding state */
|
|
||||||
private var mShouldUnbindNetwork: Boolean = false
|
|
||||||
|
|
||||||
/** Keeps track of all RxJava disposables, to make sure they are all disposed when the fragment is destroyed */
|
/** Keeps track of all RxJava disposables, to make sure they are all disposed when the fragment is destroyed */
|
||||||
protected var mDisposables = CompositeDisposable()
|
protected var mDisposables = CompositeDisposable()
|
||||||
|
@ -66,41 +58,12 @@ abstract class ConnectedFragment : Fragment(), ServiceConnection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
|
|
||||||
val intent = Intent(context, NetworkService::class.java)
|
|
||||||
if (context?.bindService(intent, this, Context.BIND_AUTO_CREATE) == true) {
|
|
||||||
mShouldUnbindNetwork = true
|
|
||||||
} else {
|
|
||||||
Log.e(TAG, "Binding to the network service failed.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPause() {
|
|
||||||
super.onPause()
|
|
||||||
|
|
||||||
// Unbinding from network service
|
|
||||||
if (mShouldUnbindNetwork) {
|
|
||||||
context?.unbindService(this)
|
|
||||||
mShouldUnbindNetwork = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
|
|
||||||
if (!mDisposables.isDisposed) mDisposables.dispose()
|
if (!mDisposables.isDisposed) mDisposables.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onServiceDisconnected(name: ComponentName?) { }
|
|
||||||
|
|
||||||
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
|
|
||||||
// We've bound to LocalService, cast the IBinder and get LocalService instance
|
|
||||||
val binder = service as NetworkService.LocalBinder
|
|
||||||
mNetworkService = binder.service
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to be implemented by all subclasses in order to be notified of JSON-RPC responses.
|
* Method to be implemented by all subclasses in order to be notified of JSON-RPC responses.
|
||||||
* @param response
|
* @param response
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
package cy.agorise.bitsybitshareswallet.fragments
|
package cy.agorise.bitsybitshareswallet.fragments
|
||||||
|
|
||||||
import android.content.ComponentName
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.IBinder
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
@ -35,7 +33,7 @@ import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
import kotlinx.android.synthetic.main.fragment_import_brainkey.*
|
import kotlinx.android.synthetic.main.fragment_import_brainkey.*
|
||||||
import org.bitcoinj.core.ECKey
|
import org.bitcoinj.core.ECKey
|
||||||
import java.text.NumberFormat
|
import java.text.NumberFormat
|
||||||
import java.util.ArrayList
|
import java.util.*
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
class ImportBrainkeyFragment : BaseAccountFragment() {
|
class ImportBrainkeyFragment : BaseAccountFragment() {
|
||||||
|
@ -249,10 +247,10 @@ class ImportBrainkeyFragment : BaseAccountFragment() {
|
||||||
if (Character.isUpperCase(brainKey.toCharArray()[brainKey.length - 1])) {
|
if (Character.isUpperCase(brainKey.toCharArray()[brainKey.length - 1])) {
|
||||||
// If the last character is an uppercase, we assume the whole brainkey
|
// If the last character is an uppercase, we assume the whole brainkey
|
||||||
// was given in capital letters and turn it to lowercase
|
// was given in capital letters and turn it to lowercase
|
||||||
getAccountFromBrainkey(brainKey.toLowerCase())
|
getAccountFromBrainkey(brainKey.toLowerCase(Locale.ROOT))
|
||||||
} else {
|
} else {
|
||||||
// Otherwise we turn the whole brainkey to capital letters
|
// Otherwise we turn the whole brainkey to capital letters
|
||||||
getAccountFromBrainkey(brainKey.toUpperCase())
|
getAccountFromBrainkey(brainKey.toUpperCase(Locale.ROOT))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If no case switching should take place, we perform the network call with
|
// If no case switching should take place, we perform the network call with
|
||||||
|
@ -274,6 +272,15 @@ class ImportBrainkeyFragment : BaseAccountFragment() {
|
||||||
keyReferencesRequestId = mNetworkService?.sendMessage(GetKeyReferences(address), GetKeyReferences.REQUIRED_API)
|
keyReferencesRequestId = mNetworkService?.sendMessage(GetKeyReferences(address), GetKeyReferences.REQUIRED_API)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onStart() {
|
||||||
|
super.onStart()
|
||||||
|
|
||||||
|
if (mNetworkService?.isConnected == true)
|
||||||
|
showConnectedState()
|
||||||
|
else
|
||||||
|
showDisconnectedState()
|
||||||
|
}
|
||||||
|
|
||||||
override fun handleJsonRpcResponse(response: JsonRpcResponse<*>) {
|
override fun handleJsonRpcResponse(response: JsonRpcResponse<*>) {
|
||||||
if (response.id == keyReferencesRequestId) {
|
if (response.id == keyReferencesRequestId) {
|
||||||
handleBrainKeyAccountReferences(response.result)
|
handleBrainKeyAccountReferences(response.result)
|
||||||
|
@ -289,7 +296,24 @@ class ImportBrainkeyFragment : BaseAccountFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handleConnectionStatusUpdate(connectionStatusUpdate: ConnectionStatusUpdate) {
|
override fun handleConnectionStatusUpdate(connectionStatusUpdate: ConnectionStatusUpdate) {
|
||||||
Log.d(TAG, "handleConnectionStatusUpdate. code: " + connectionStatusUpdate.updateCode)
|
when (connectionStatusUpdate.updateCode) {
|
||||||
|
ConnectionStatusUpdate.CONNECTED -> {
|
||||||
|
showConnectedState()
|
||||||
|
}
|
||||||
|
ConnectionStatusUpdate.DISCONNECTED -> {
|
||||||
|
showDisconnectedState()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showConnectedState() {
|
||||||
|
tvNetworkStatus.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null,
|
||||||
|
resources.getDrawable(R.drawable.ic_connected, null), null)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showDisconnectedState() {
|
||||||
|
tvNetworkStatus.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null,
|
||||||
|
resources.getDrawable(R.drawable.ic_disconnected, null), null)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -385,18 +409,4 @@ class ImportBrainkeyFragment : BaseAccountFragment() {
|
||||||
mHandler.postDelayed(this, Constants.BLOCK_PERIOD)
|
mHandler.postDelayed(this, Constants.BLOCK_PERIOD)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onServiceDisconnected(name: ComponentName?) {
|
|
||||||
super.onServiceDisconnected(name)
|
|
||||||
|
|
||||||
tvNetworkStatus.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null,
|
|
||||||
resources.getDrawable(R.drawable.ic_disconnected, null), null)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
|
|
||||||
super.onServiceConnected(name, service)
|
|
||||||
|
|
||||||
tvNetworkStatus.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null,
|
|
||||||
resources.getDrawable(R.drawable.ic_connected, null), null)
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -3,7 +3,6 @@ package cy.agorise.bitsybitshareswallet.fragments
|
||||||
import android.content.*
|
import android.content.*
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.IBinder
|
|
||||||
import android.preference.PreferenceManager
|
import android.preference.PreferenceManager
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
@ -190,6 +189,15 @@ class SettingsFragment : ConnectedFragment(), BaseSecurityLockDialog.OnPINPatter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onStart() {
|
||||||
|
super.onStart()
|
||||||
|
|
||||||
|
if (mNetworkService?.isConnected == true)
|
||||||
|
showConnectedState()
|
||||||
|
else
|
||||||
|
showDisconnectedState()
|
||||||
|
}
|
||||||
|
|
||||||
override fun handleJsonRpcResponse(response: JsonRpcResponse<*>) {
|
override fun handleJsonRpcResponse(response: JsonRpcResponse<*>) {
|
||||||
if (responseMap.containsKey(response.id)) {
|
if (responseMap.containsKey(response.id)) {
|
||||||
when (responseMap[response.id]) {
|
when (responseMap[response.id]) {
|
||||||
|
@ -201,7 +209,26 @@ class SettingsFragment : ConnectedFragment(), BaseSecurityLockDialog.OnPINPatter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handleConnectionStatusUpdate(connectionStatusUpdate: ConnectionStatusUpdate) { }
|
override fun handleConnectionStatusUpdate(connectionStatusUpdate: ConnectionStatusUpdate) {
|
||||||
|
when (connectionStatusUpdate.updateCode) {
|
||||||
|
ConnectionStatusUpdate.CONNECTED -> {
|
||||||
|
showConnectedState()
|
||||||
|
}
|
||||||
|
ConnectionStatusUpdate.DISCONNECTED -> {
|
||||||
|
showDisconnectedState()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showConnectedState() {
|
||||||
|
tvNetworkStatus.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null,
|
||||||
|
resources.getDrawable(R.drawable.ic_connected, null), null)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showDisconnectedState() {
|
||||||
|
tvNetworkStatus.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null,
|
||||||
|
resources.getDrawable(R.drawable.ic_disconnected, null), null)
|
||||||
|
}
|
||||||
|
|
||||||
/** Handles the result of the [GetDynamicGlobalProperties] api call to obtain the current block number and update
|
/** Handles the result of the [GetDynamicGlobalProperties] api call to obtain the current block number and update
|
||||||
* it in the Nodes Dialog */
|
* it in the Nodes Dialog */
|
||||||
|
@ -531,19 +558,5 @@ class SettingsFragment : ConnectedFragment(), BaseSecurityLockDialog.OnPINPatter
|
||||||
activity?.finish()
|
activity?.finish()
|
||||||
activity?.startActivity(intent)
|
activity?.startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onServiceDisconnected(name: ComponentName?) {
|
|
||||||
super.onServiceDisconnected(name)
|
|
||||||
|
|
||||||
tvNetworkStatus.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null,
|
|
||||||
resources.getDrawable(R.drawable.ic_disconnected, null), null)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
|
|
||||||
super.onServiceConnected(name, service)
|
|
||||||
|
|
||||||
tvNetworkStatus.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null,
|
|
||||||
resources.getDrawable(R.drawable.ic_connected, null), null)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
package cy.agorise.bitsybitshareswallet.network
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.app.Application.ActivityLifecycleCallbacks
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.Handler
|
||||||
|
import cy.agorise.graphenej.api.android.NetworkService
|
||||||
|
import cy.agorise.graphenej.stats.ExponentialMovingAverage
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class used to manage the connection status of the NetworkService.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* The basic idea here is to keep track of the sequence of activity life cycle callbacks so that we
|
||||||
|
* can infer when the user has left the app and the node connection can be salfely shut down.
|
||||||
|
*/
|
||||||
|
class NetworkServiceManager(nodes: List<String>) :
|
||||||
|
ActivityLifecycleCallbacks {
|
||||||
|
/**
|
||||||
|
* Handler instance used to schedule tasks back to the main thread
|
||||||
|
*/
|
||||||
|
private val mHandler = Handler()
|
||||||
|
private var mNetworkService: NetworkService? = null
|
||||||
|
private val mNodeUrls: Array<String> = nodes.toTypedArray()
|
||||||
|
/**
|
||||||
|
* Runnable used to schedule a service disconnection once the app is not visible to the user for
|
||||||
|
* more than DISCONNECT_DELAY milliseconds.
|
||||||
|
*/
|
||||||
|
private val mDisconnectRunnable = Runnable {
|
||||||
|
if (mNetworkService != null) {
|
||||||
|
mNetworkService?.stop()
|
||||||
|
mNetworkService = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityCreated(activity: Activity, bundle: Bundle) {}
|
||||||
|
override fun onActivityStarted(activity: Activity) {}
|
||||||
|
override fun onActivityResumed(activity: Activity?) {
|
||||||
|
mHandler.removeCallbacks(mDisconnectRunnable)
|
||||||
|
if (mNetworkService == null) {
|
||||||
|
mNetworkService = NetworkService.getInstance()
|
||||||
|
mNetworkService?.start(mNodeUrls, ExponentialMovingAverage.DEFAULT_ALPHA)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityPaused(activity: Activity) {
|
||||||
|
mHandler.postDelayed(
|
||||||
|
mDisconnectRunnable,
|
||||||
|
DISCONNECT_DELAY.toLong()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityStopped(activity: Activity) {}
|
||||||
|
override fun onActivitySaveInstanceState(
|
||||||
|
activity: Activity,
|
||||||
|
bundle: Bundle
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityDestroyed(activity: Activity) {}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* Constant used to specify how long will the app wait for another activity to go through its starting life
|
||||||
|
* cycle events before running the teardownConnectionTask task.
|
||||||
|
*
|
||||||
|
* This is used as a means to detect whether or not the user has left the app.
|
||||||
|
*/
|
||||||
|
private const val DISCONNECT_DELAY = 1500
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,10 +1,6 @@
|
||||||
package cy.agorise.bitsybitshareswallet.processors
|
package cy.agorise.bitsybitshareswallet.processors
|
||||||
|
|
||||||
import android.content.ComponentName
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
|
||||||
import android.content.ServiceConnection
|
|
||||||
import android.os.IBinder
|
|
||||||
import android.preference.PreferenceManager
|
import android.preference.PreferenceManager
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import cy.agorise.bitsybitshareswallet.database.entities.Transfer
|
import cy.agorise.bitsybitshareswallet.database.entities.Transfer
|
||||||
|
@ -29,6 +25,7 @@ import org.bitcoinj.core.DumpedPrivateKey
|
||||||
import org.bitcoinj.core.ECKey
|
import org.bitcoinj.core.ECKey
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.crypto.AEADBadTagException
|
import javax.crypto.AEADBadTagException
|
||||||
|
import kotlin.math.floor
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is responsible for loading the local database with all past transfer operations of the
|
* This class is responsible for loading the local database with all past transfer operations of the
|
||||||
|
@ -66,33 +63,14 @@ class TransfersLoader(private var mContext: Context?) {
|
||||||
private var authorityRepository: AuthorityRepository? = null
|
private var authorityRepository: AuthorityRepository? = null
|
||||||
|
|
||||||
/* Network service connection */
|
/* Network service connection */
|
||||||
private var mNetworkService: NetworkService? = null
|
private var mNetworkService: NetworkService? = NetworkService.getInstance()
|
||||||
|
|
||||||
/* Counter used to keep track of the transfer history batch count */
|
/* Counter used to keep track of the transfer history batch count */
|
||||||
private var historicalTransferCount = 0
|
private var historicalTransferCount = 0
|
||||||
|
|
||||||
/** Flag used to keep track of the NetworkService binding state */
|
|
||||||
private var mBound: Boolean = false
|
|
||||||
|
|
||||||
// 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>()
|
||||||
|
|
||||||
private val mConnection = object : ServiceConnection {
|
|
||||||
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
|
|
||||||
// We've bound to LocalService, cast the IBinder and get LocalService instance
|
|
||||||
val binder = service as NetworkService.LocalBinder
|
|
||||||
mNetworkService = binder.service
|
|
||||||
mBound = true
|
|
||||||
|
|
||||||
// Start the transfers update
|
|
||||||
startTransfersUpdateProcedure()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onServiceDisconnected(name: ComponentName?) {
|
|
||||||
mBound = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
transferRepository = TransferRepository(mContext!!)
|
transferRepository = TransferRepository(mContext!!)
|
||||||
authorityRepository = AuthorityRepository(mContext!!)
|
authorityRepository = AuthorityRepository(mContext!!)
|
||||||
|
@ -138,14 +116,8 @@ class TransfersLoader(private var mContext: Context?) {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
onStart()
|
// Start the transfers update
|
||||||
}
|
startTransfersUpdateProcedure()
|
||||||
}
|
|
||||||
|
|
||||||
private fun onStart() {
|
|
||||||
// Bind to LocalService
|
|
||||||
Intent(mContext, NetworkService::class.java).also { intent ->
|
|
||||||
mContext?.bindService(intent, mConnection, Context.BIND_AUTO_CREATE)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +137,7 @@ class TransfersLoader(private var mContext: Context?) {
|
||||||
if (transferCount > 0) {
|
if (transferCount > 0) {
|
||||||
// If we already have some transfers in the database, we might want to skip the request
|
// If we already have some transfers in the database, we might want to skip the request
|
||||||
// straight to the last batch
|
// straight to the last batch
|
||||||
historicalTransferCount = Math.floor((transferCount /
|
historicalTransferCount = floor((transferCount /
|
||||||
HISTORICAL_TRANSFER_BATCH_SIZE).toDouble()).toInt()
|
HISTORICAL_TRANSFER_BATCH_SIZE).toDouble()).toInt()
|
||||||
}
|
}
|
||||||
// Retrieving account transactions
|
// Retrieving account transactions
|
||||||
|
@ -257,10 +229,10 @@ class TransfersLoader(private var mContext: Context?) {
|
||||||
val memo = op.memo
|
val memo = op.memo
|
||||||
if (memo.byteMessage != null) {
|
if (memo.byteMessage != null) {
|
||||||
try {
|
try {
|
||||||
if (memo.destination.equals(myAddress)) {
|
if (memo.destination == myAddress) {
|
||||||
val decryptedMessage = Memo.decryptMessage(memoKey, memo.source, memo.nonce, memo.byteMessage)
|
val decryptedMessage = Memo.decryptMessage(memoKey, memo.source, memo.nonce, memo.byteMessage)
|
||||||
memo.plaintextMessage = decryptedMessage
|
memo.plaintextMessage = decryptedMessage
|
||||||
}else if(memo.source.equals(myAddress)){
|
}else if(memo.source == myAddress){
|
||||||
val decryptedMessage = Memo.decryptMessage(memoKey, memo.destination, memo.nonce, memo.byteMessage)
|
val decryptedMessage = Memo.decryptMessage(memoKey, memo.destination, memo.nonce, memo.byteMessage)
|
||||||
memo.plaintextMessage = decryptedMessage
|
memo.plaintextMessage = decryptedMessage
|
||||||
}
|
}
|
||||||
|
@ -271,7 +243,7 @@ class TransfersLoader(private var mContext: Context?) {
|
||||||
Log.e(TAG, "NullPointerException. Msg: " + e.message)
|
Log.e(TAG, "NullPointerException. Msg: " + e.message)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "Exception while decoding memo. Msg: " + e.message)
|
Log.e(TAG, "Exception while decoding memo. Msg: " + e.message)
|
||||||
Log.e(TAG,"Exception type: " + e)
|
Log.e(TAG, "Exception type: $e")
|
||||||
for(element in e.stackTrace){
|
for(element in e.stackTrace){
|
||||||
Log.e(TAG, String.format("%s#%s:%d", element.className, element.methodName, element.lineNumber))
|
Log.e(TAG, String.format("%s#%s:%d", element.className, element.methodName, element.lineNumber))
|
||||||
}
|
}
|
||||||
|
@ -300,13 +272,6 @@ class TransfersLoader(private var mContext: Context?) {
|
||||||
Log.d(TAG, "Destroying TransfersLoader")
|
Log.d(TAG, "Destroying TransfersLoader")
|
||||||
if (!mDisposables.isDisposed) mDisposables.dispose()
|
if (!mDisposables.isDisposed) mDisposables.dispose()
|
||||||
|
|
||||||
try {
|
|
||||||
if (mBound && mNetworkService != null)
|
|
||||||
mContext?.unbindService(mConnection)
|
|
||||||
} catch (e: IllegalArgumentException) {
|
|
||||||
Log.d(TAG, "Avoid crash related to Service not registered: ${e.message}")
|
|
||||||
}
|
|
||||||
mBound = false
|
|
||||||
mContext = null
|
mContext = null
|
||||||
mNetworkService = null
|
mNetworkService = null
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,6 @@ class NodeRepository(private val nodeDao: NodeDao) {
|
||||||
suspend fun getFormattedNodes(): Pair<String, Boolean> {
|
suspend fun getFormattedNodes(): Pair<String, Boolean> {
|
||||||
val nodes = nodeDao.getSortedNodes()
|
val nodes = nodeDao.getSortedNodes()
|
||||||
|
|
||||||
// TODO verify if this is the best way to fire and forget launch a coroutine inside another coroutine
|
|
||||||
// Launches a job to refresh the list of nodes into the database, without blocking the
|
// Launches a job to refresh the list of nodes into the database, without blocking the
|
||||||
// execution of this function, so that the formatted nodes can be returned immediately
|
// execution of this function, so that the formatted nodes can be returned immediately
|
||||||
// without waiting until the nodes have been updated in the database.
|
// without waiting until the nodes have been updated in the database.
|
||||||
|
|
|
@ -3,9 +3,8 @@ package cy.agorise.bitsybitshareswallet.utils
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import com.crashlytics.android.Crashlytics
|
import com.crashlytics.android.Crashlytics
|
||||||
import cy.agorise.bitsybitshareswallet.database.BitsyDatabase
|
import cy.agorise.bitsybitshareswallet.database.BitsyDatabase
|
||||||
|
import cy.agorise.bitsybitshareswallet.network.NetworkServiceManager
|
||||||
import cy.agorise.bitsybitshareswallet.repositories.NodeRepository
|
import cy.agorise.bitsybitshareswallet.repositories.NodeRepository
|
||||||
import cy.agorise.graphenej.api.ApiAccess
|
|
||||||
import cy.agorise.graphenej.api.android.NetworkServiceManager
|
|
||||||
import io.reactivex.plugins.RxJavaPlugins
|
import io.reactivex.plugins.RxJavaPlugins
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
@ -46,18 +45,9 @@ class BitsyApplication : Application() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun startNetworkServiceConnection() {
|
private suspend fun startNetworkServiceConnection() {
|
||||||
// Specifying some important information regarding the connection, such as the
|
|
||||||
// credentials and the requested API accesses
|
|
||||||
val requestedApis = ApiAccess.API_DATABASE or ApiAccess.API_HISTORY or ApiAccess.API_NETWORK_BROADCAST
|
|
||||||
val (nodes, autoConnect) = mNodeRepository.getFormattedNodes()
|
val (nodes, autoConnect) = mNodeRepository.getFormattedNodes()
|
||||||
val networkManager = NetworkServiceManager.Builder()
|
|
||||||
.setUserName("")
|
val networkManager = NetworkServiceManager(nodes.split(","))
|
||||||
.setPassword("")
|
|
||||||
.setRequestedApis(requestedApis)
|
|
||||||
.setCustomNodeUrls(nodes)
|
|
||||||
.setAutoConnect(autoConnect)
|
|
||||||
.setNodeLatencyVerification(true)
|
|
||||||
.build(this)
|
|
||||||
/*
|
/*
|
||||||
* Registering this class as a listener to all activity's callback cycle events, in order to
|
* Registering this class as a listener to all activity's callback cycle events, in order to
|
||||||
* better estimate when the user has left the app and it is safe to disconnect the websocket connection
|
* better estimate when the user has left the app and it is safe to disconnect the websocket connection
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 1129a92aa3e4d1ceeac6826fcfe154bf909930fe
|
Subproject commit 3d5a57f8961c76fc2cadb327c86374d30c6692b7
|
Loading…
Reference in a new issue