2019-01-04 22:50:56 +00:00
|
|
|
package cy.agorise.bitsybitshareswallet.fragments
|
2018-11-21 23:43:51 +00:00
|
|
|
|
2019-01-11 19:46:50 +00:00
|
|
|
import android.content.ComponentName
|
2018-11-21 23:43:51 +00:00
|
|
|
import android.os.Bundle
|
2019-01-11 19:46:50 +00:00
|
|
|
import android.os.Handler
|
|
|
|
import android.os.IBinder
|
2018-11-23 02:13:10 +00:00
|
|
|
import android.util.Log
|
2019-01-04 22:50:56 +00:00
|
|
|
import android.view.LayoutInflater
|
|
|
|
import android.view.View
|
|
|
|
import android.view.ViewGroup
|
|
|
|
import androidx.appcompat.widget.Toolbar
|
2019-01-05 21:23:42 +00:00
|
|
|
import androidx.navigation.Navigation
|
2018-11-23 02:13:10 +00:00
|
|
|
import com.afollestad.materialdialogs.MaterialDialog
|
2019-01-11 19:52:55 +00:00
|
|
|
import com.afollestad.materialdialogs.callbacks.onDismiss
|
2019-01-11 19:46:50 +00:00
|
|
|
import com.afollestad.materialdialogs.list.customListAdapter
|
2018-11-24 15:11:57 +00:00
|
|
|
import com.afollestad.materialdialogs.list.listItemsSingleChoice
|
2019-02-21 17:16:04 +00:00
|
|
|
import com.crashlytics.android.Crashlytics
|
2018-12-24 16:55:54 +00:00
|
|
|
import com.jakewharton.rxbinding3.widget.textChanges
|
2019-01-11 19:46:50 +00:00
|
|
|
import cy.agorise.bitsybitshareswallet.BuildConfig
|
2018-11-21 23:43:51 +00:00
|
|
|
import cy.agorise.bitsybitshareswallet.R
|
2019-01-11 19:46:50 +00:00
|
|
|
import cy.agorise.bitsybitshareswallet.adapters.FullNodesAdapter
|
2018-11-22 21:40:33 +00:00
|
|
|
import cy.agorise.bitsybitshareswallet.utils.Constants
|
2019-01-04 22:50:56 +00:00
|
|
|
import cy.agorise.bitsybitshareswallet.utils.toast
|
2018-11-24 15:11:57 +00:00
|
|
|
import cy.agorise.graphenej.*
|
2018-11-23 02:13:10 +00:00
|
|
|
import cy.agorise.graphenej.api.ConnectionStatusUpdate
|
|
|
|
import cy.agorise.graphenej.api.calls.GetAccounts
|
2019-01-11 19:46:50 +00:00
|
|
|
import cy.agorise.graphenej.api.calls.GetDynamicGlobalProperties
|
2018-11-23 02:13:10 +00:00
|
|
|
import cy.agorise.graphenej.api.calls.GetKeyReferences
|
|
|
|
import cy.agorise.graphenej.models.AccountProperties
|
2019-01-11 19:46:50 +00:00
|
|
|
import cy.agorise.graphenej.models.DynamicGlobalProperties
|
2018-11-23 02:13:10 +00:00
|
|
|
import cy.agorise.graphenej.models.JsonRpcResponse
|
2018-12-11 19:25:15 +00:00
|
|
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
2019-01-04 22:50:56 +00:00
|
|
|
import kotlinx.android.synthetic.main.fragment_import_brainkey.*
|
2018-11-23 02:13:10 +00:00
|
|
|
import org.bitcoinj.core.ECKey
|
2019-01-11 19:46:50 +00:00
|
|
|
import java.text.NumberFormat
|
2018-11-23 02:13:10 +00:00
|
|
|
import java.util.ArrayList
|
2018-12-11 19:25:15 +00:00
|
|
|
import java.util.concurrent.TimeUnit
|
2018-11-21 23:43:51 +00:00
|
|
|
|
2019-01-08 19:27:18 +00:00
|
|
|
class ImportBrainkeyFragment : BaseAccountFragment() {
|
2019-01-11 19:46:50 +00:00
|
|
|
|
2019-01-04 22:50:56 +00:00
|
|
|
companion object {
|
2019-02-11 22:10:14 +00:00
|
|
|
private const val TAG = "ImportBrainkeyFragment"
|
2019-01-04 22:50:56 +00:00
|
|
|
}
|
2018-11-22 21:40:33 +00:00
|
|
|
|
2019-01-04 22:50:56 +00:00
|
|
|
/** User account associated with the key derived from the brainkey that the user just typed in */
|
2018-11-22 21:40:33 +00:00
|
|
|
private var mUserAccount: UserAccount? = null
|
|
|
|
|
|
|
|
/**
|
|
|
|
* List of user account candidates, this is required in order to allow the user to select a single
|
|
|
|
* user account in case one key (derived from the brainkey) controls more than one account.
|
|
|
|
*/
|
|
|
|
private var mUserAccountCandidates: List<UserAccount>? = null
|
|
|
|
|
|
|
|
private var mKeyReferencesAttempts = 0
|
|
|
|
|
2019-01-10 21:07:27 +00:00
|
|
|
private var keyReferencesRequestId: Long? = null
|
|
|
|
private var getAccountsRequestId: Long? = null
|
2018-11-22 21:40:33 +00:00
|
|
|
|
2018-12-11 19:25:15 +00:00
|
|
|
private var isPINValid = false
|
|
|
|
private var isPINConfirmationValid = false
|
|
|
|
private var isBrainKeyValid = false
|
|
|
|
|
2019-01-11 19:46:50 +00:00
|
|
|
// Dialog displaying the list of nodes and their latencies
|
|
|
|
private var mNodesDialog: MaterialDialog? = null
|
|
|
|
|
|
|
|
/** Adapter that holds the FullNode list used in the Bitshares nodes modal */
|
2019-08-29 17:09:34 +00:00
|
|
|
private var nodesAdapter: FullNodesAdapter? = null
|
2019-01-11 19:46:50 +00:00
|
|
|
|
|
|
|
/** Handler that will be used to make recurrent calls to get the latest BitShares block number*/
|
|
|
|
private val mHandler = Handler()
|
|
|
|
|
2019-01-04 22:50:56 +00:00
|
|
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
|
|
|
// Remove up navigation icon from the toolbar
|
|
|
|
val toolbar: Toolbar? = activity?.findViewById(R.id.toolbar)
|
|
|
|
toolbar?.navigationIcon = null
|
|
|
|
|
|
|
|
return inflater.inflate(R.layout.fragment_import_brainkey, container, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
|
|
super.onViewCreated(view, savedInstanceState)
|
2018-11-22 21:40:33 +00:00
|
|
|
|
2019-02-21 17:16:04 +00:00
|
|
|
Crashlytics.setString(Constants.CRASHLYTICS_KEY_LAST_SCREEN, TAG)
|
|
|
|
|
2018-12-11 19:25:15 +00:00
|
|
|
// Use RxJava Debounce to update the PIN error only after the user stops writing for > 500 ms
|
|
|
|
mDisposables.add(
|
2018-12-24 16:55:54 +00:00
|
|
|
tietPin.textChanges()
|
2018-12-11 19:25:15 +00:00
|
|
|
.skipInitialValue()
|
|
|
|
.debounce(500, TimeUnit.MILLISECONDS)
|
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
2019-03-17 15:38:36 +00:00
|
|
|
.subscribe(
|
|
|
|
{ validatePIN() },
|
|
|
|
{ Crashlytics.log(Log.DEBUG, TAG, it.message) }
|
|
|
|
)
|
2018-12-11 19:25:15 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Use RxJava Debounce to update the PIN Confirmation error only after the user stops writing for > 500 ms
|
|
|
|
mDisposables.add(
|
2018-12-24 16:55:54 +00:00
|
|
|
tietPinConfirmation.textChanges()
|
2018-12-11 19:25:15 +00:00
|
|
|
.skipInitialValue()
|
|
|
|
.debounce(500, TimeUnit.MILLISECONDS)
|
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
2019-03-17 15:38:36 +00:00
|
|
|
.subscribe(
|
|
|
|
{ validatePINConfirmation() },
|
|
|
|
{ Crashlytics.log(Log.DEBUG, TAG, it.message) }
|
|
|
|
)
|
2018-12-11 19:25:15 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Use RxJava Debounce to update the BrainKey error only after the user stops writing for > 500 ms
|
|
|
|
mDisposables.add(
|
2018-12-24 16:55:54 +00:00
|
|
|
tietBrainKey.textChanges()
|
2018-12-11 19:25:15 +00:00
|
|
|
.skipInitialValue()
|
|
|
|
.debounce(500, TimeUnit.MILLISECONDS)
|
|
|
|
.map { it.toString().trim() }
|
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
2019-03-17 15:38:36 +00:00
|
|
|
.subscribe(
|
|
|
|
{ validateBrainKey(it) },
|
|
|
|
{ Crashlytics.log(Log.DEBUG, TAG, it.message) }
|
|
|
|
)
|
2018-12-11 19:25:15 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
btnImport.isEnabled = false
|
|
|
|
btnImport.setOnClickListener { verifyBrainKey(false) }
|
2019-01-05 21:23:42 +00:00
|
|
|
|
|
|
|
btnCreate.setOnClickListener (
|
|
|
|
Navigation.createNavigateOnClickListener(R.id.create_account_action)
|
|
|
|
)
|
2019-01-11 19:46:50 +00:00
|
|
|
|
2019-08-29 17:09:34 +00:00
|
|
|
tvNetworkStatus.setOnClickListener { v -> showNodesDialog(v) }
|
|
|
|
}
|
2019-01-11 19:46:50 +00:00
|
|
|
|
2019-08-29 17:09:34 +00:00
|
|
|
private fun showNodesDialog(v: View) {
|
|
|
|
if (mNetworkService != null) {
|
|
|
|
val fullNodes = mNetworkService!!.nodes
|
2019-01-11 19:46:50 +00:00
|
|
|
|
2019-08-29 17:09:34 +00:00
|
|
|
nodesAdapter = FullNodesAdapter(v.context)
|
|
|
|
nodesAdapter?.add(fullNodes)
|
2019-01-11 19:46:50 +00:00
|
|
|
|
2019-08-29 17:09:34 +00:00
|
|
|
// PublishSubject used to announce full node latencies updates
|
|
|
|
val fullNodePublishSubject = mNetworkService!!.nodeLatencyObservable ?: return
|
2019-01-11 19:46:50 +00:00
|
|
|
|
2019-08-29 17:09:34 +00:00
|
|
|
val nodesDisposable = fullNodePublishSubject
|
|
|
|
.subscribeOn(AndroidSchedulers.mainThread())
|
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
|
|
|
.subscribe(
|
|
|
|
{ fullNode ->
|
|
|
|
if (!fullNode.isRemoved)
|
|
|
|
nodesAdapter?.add(fullNode)
|
|
|
|
else
|
|
|
|
nodesAdapter?.remove(fullNode)
|
|
|
|
}, {
|
|
|
|
Log.e(TAG, "nodeLatencyObserver.onError.Msg: " + it.message)
|
|
|
|
}
|
|
|
|
)
|
2019-01-11 19:46:50 +00:00
|
|
|
|
2019-08-29 17:09:34 +00:00
|
|
|
mNodesDialog = MaterialDialog(v.context).show {
|
|
|
|
title(text = String.format("%s v%s", getString(R.string.app_name), BuildConfig.VERSION_NAME))
|
|
|
|
message(text = getString(R.string.title__bitshares_nodes_dialog, "-------"))
|
|
|
|
customListAdapter(nodesAdapter as FullNodesAdapter)
|
|
|
|
negativeButton(android.R.string.ok)
|
|
|
|
onDismiss {
|
|
|
|
mHandler.removeCallbacks(mRequestDynamicGlobalPropertiesTask)
|
|
|
|
nodesDisposable.dispose()
|
|
|
|
}
|
2019-01-11 19:46:50 +00:00
|
|
|
}
|
2019-08-29 17:09:34 +00:00
|
|
|
|
|
|
|
// Registering a recurrent task used to poll for dynamic global properties requests
|
|
|
|
mHandler.post(mRequestDynamicGlobalPropertiesTask)
|
2019-01-11 19:46:50 +00:00
|
|
|
}
|
2018-12-11 19:25:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private fun validatePIN() {
|
|
|
|
val pin = tietPin.text.toString()
|
|
|
|
|
|
|
|
if (pin.length < Constants.MIN_PIN_LENGTH) {
|
|
|
|
tilPin.error = getString(R.string.error__pin_too_short)
|
|
|
|
isPINValid = false
|
|
|
|
} else {
|
|
|
|
tilPin.isErrorEnabled = false
|
|
|
|
isPINValid = true
|
2018-11-23 02:13:10 +00:00
|
|
|
}
|
|
|
|
|
2018-12-11 19:25:15 +00:00
|
|
|
validatePINConfirmation()
|
2018-11-22 21:40:33 +00:00
|
|
|
}
|
|
|
|
|
2018-12-11 19:25:15 +00:00
|
|
|
private fun validatePINConfirmation() {
|
|
|
|
val pinConfirmation = tietPinConfirmation.text.toString()
|
2018-11-22 21:40:33 +00:00
|
|
|
|
2018-12-11 19:25:15 +00:00
|
|
|
if (pinConfirmation != tietPin.text.toString()) {
|
2018-11-22 21:40:33 +00:00
|
|
|
tilPinConfirmation.error = getString(R.string.error__pin_mismatch)
|
2018-12-11 19:25:15 +00:00
|
|
|
isPINConfirmationValid = false
|
|
|
|
} else {
|
|
|
|
tilPinConfirmation.isErrorEnabled = false
|
|
|
|
isPINConfirmationValid = true
|
|
|
|
}
|
|
|
|
|
|
|
|
enableDisableImportButton()
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun validateBrainKey(brainKey: String) {
|
|
|
|
if (brainKey.isEmpty() || !brainKey.contains(" ") || brainKey.split(" ").size !in 12..16) {
|
2018-11-22 21:40:33 +00:00
|
|
|
tilBrainKey.error = getString(R.string.error__enter_correct_brainkey)
|
2018-12-11 19:25:15 +00:00
|
|
|
isBrainKeyValid = false
|
|
|
|
} else {
|
|
|
|
tilBrainKey.isErrorEnabled = false
|
|
|
|
isBrainKeyValid = true
|
2018-11-22 21:40:33 +00:00
|
|
|
}
|
|
|
|
|
2018-12-11 19:25:15 +00:00
|
|
|
enableDisableImportButton()
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun enableDisableImportButton() {
|
|
|
|
btnImport.isEnabled = (isPINValid && isPINConfirmationValid && isBrainKeyValid)
|
2018-11-21 23:43:51 +00:00
|
|
|
}
|
2018-11-23 02:13:10 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Method that will verify the provided brain key, and if valid will retrieve the account information
|
|
|
|
* associated to the user id.
|
|
|
|
*
|
|
|
|
* This method will perform a network lookup to look which accounts use the public key associated
|
|
|
|
* with the user provided brainkey.
|
|
|
|
*
|
|
|
|
* Some sources use brainkeys in capital letters, while others use lowercase. The activity should
|
|
|
|
* initially call this method with the 'switchCase' parameter as false, in order to try the
|
|
|
|
* brainkey as it was provided by the user.
|
|
|
|
*
|
|
|
|
* But in case this lookup fails, it is expected that the activity makes another attempt. This time
|
|
|
|
* with the 'switchCase' argument set to true.
|
|
|
|
*
|
|
|
|
* If both attempts fail, then we can be certain that the provided brainkey is not currently
|
|
|
|
* associated with any account.
|
|
|
|
*
|
|
|
|
* @param switchCase Whether to switch the case used in the brainkey or not.
|
|
|
|
*/
|
|
|
|
private fun verifyBrainKey(switchCase: Boolean) {
|
|
|
|
//showDialog("", getString(R.string.importing_your_wallet))
|
2019-01-16 15:02:18 +00:00
|
|
|
val brainKey = tietBrainKey.text.toString().trim()
|
2018-11-23 02:13:10 +00:00
|
|
|
// Should we switch the brainkey case?
|
|
|
|
if (switchCase) {
|
|
|
|
if (Character.isUpperCase(brainKey.toCharArray()[brainKey.length - 1])) {
|
|
|
|
// If the last character is an uppercase, we assume the whole brainkey
|
|
|
|
// was given in capital letters and turn it to lowercase
|
|
|
|
getAccountFromBrainkey(brainKey.toLowerCase())
|
|
|
|
} else {
|
|
|
|
// Otherwise we turn the whole brainkey to capital letters
|
|
|
|
getAccountFromBrainkey(brainKey.toUpperCase())
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// If no case switching should take place, we perform the network call with
|
|
|
|
// the brainkey as it was provided to us.
|
|
|
|
getAccountFromBrainkey(brainKey)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Method that will send a network request asking for all the accounts that make use of the
|
|
|
|
* key derived from a give brain key.
|
|
|
|
*
|
|
|
|
* @param brainKey The brain key the user has just typed
|
|
|
|
*/
|
|
|
|
private fun getAccountFromBrainkey(brainKey: String) {
|
|
|
|
mBrainKey = BrainKey(brainKey, 0)
|
|
|
|
val address = Address(ECKey.fromPublicOnly(mBrainKey!!.privateKey.pubKey))
|
|
|
|
Log.d(TAG, String.format("Brainkey would generate address: %s", address.toString()))
|
2019-01-10 21:07:27 +00:00
|
|
|
keyReferencesRequestId = mNetworkService?.sendMessage(GetKeyReferences(address), GetKeyReferences.REQUIRED_API)
|
2018-11-23 02:13:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun handleJsonRpcResponse(response: JsonRpcResponse<*>) {
|
|
|
|
if (response.id == keyReferencesRequestId) {
|
2019-01-10 21:07:27 +00:00
|
|
|
handleBrainKeyAccountReferences(response.result)
|
|
|
|
} else if (response.id == getAccountsRequestId) {
|
|
|
|
handleAccountProperties(response.result)
|
2019-01-11 19:46:50 +00:00
|
|
|
} else if (response.result is DynamicGlobalProperties) {
|
|
|
|
val dynamicGlobalProperties = response.result as DynamicGlobalProperties
|
|
|
|
if (mNodesDialog != null && mNodesDialog?.isShowing == true) {
|
|
|
|
val blockNumber = NumberFormat.getInstance().format(dynamicGlobalProperties.head_block_number)
|
|
|
|
mNodesDialog?.message(text = getString(R.string.title__bitshares_nodes_dialog, blockNumber))
|
|
|
|
}
|
2019-01-10 21:07:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun handleConnectionStatusUpdate(connectionStatusUpdate: ConnectionStatusUpdate) {
|
|
|
|
Log.d(TAG, "handleConnectionStatusUpdate. code: " + connectionStatusUpdate.updateCode)
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handles the response from the NetworkService when the app asks for the accounts that are controlled by a
|
|
|
|
* specified BrainKey
|
|
|
|
*/
|
|
|
|
private fun handleBrainKeyAccountReferences(result: Any?) {
|
2019-01-16 15:02:18 +00:00
|
|
|
if (result !is List<*> || result[0] !is List<*>) {
|
|
|
|
context?.toast(getString(R.string.error__invalid_brainkey))
|
2019-01-10 21:07:27 +00:00
|
|
|
return
|
2019-01-16 15:02:18 +00:00
|
|
|
}
|
2019-01-10 21:07:27 +00:00
|
|
|
|
|
|
|
val resp = result as List<List<UserAccount>>
|
|
|
|
val accountList: List<UserAccount> = resp[0].distinct()
|
|
|
|
|
|
|
|
if (accountList.isEmpty()) {
|
|
|
|
if (mKeyReferencesAttempts == 0) {
|
2018-11-23 02:13:10 +00:00
|
|
|
mKeyReferencesAttempts++
|
|
|
|
verifyBrainKey(true)
|
|
|
|
} else {
|
2019-01-10 21:07:27 +00:00
|
|
|
context?.toast(getString(R.string.error__invalid_brainkey))
|
2018-11-23 02:13:10 +00:00
|
|
|
}
|
2019-01-10 21:07:27 +00:00
|
|
|
} else if (accountList.size == 1) {
|
|
|
|
// If we only found one account linked to this key, then we just proceed
|
|
|
|
// trying to find out the account name
|
|
|
|
mUserAccount = accountList[0]
|
|
|
|
getAccountsRequestId =
|
|
|
|
mNetworkService?.sendMessage(GetAccounts(mUserAccount), GetAccounts.REQUIRED_API)
|
|
|
|
} else {
|
|
|
|
// If we found more than one account linked to this key, we must also
|
|
|
|
// find out the account names, but the procedure is a bit different in
|
|
|
|
// that after having those, we must still ask the user to decide which
|
|
|
|
// account should be imported.
|
|
|
|
mUserAccountCandidates = accountList
|
|
|
|
getAccountsRequestId = mNetworkService?.sendMessage(
|
|
|
|
GetAccounts(mUserAccountCandidates),
|
|
|
|
GetAccounts.REQUIRED_API
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handles the response from the NetworkService when the app asks for the AccountProperties of a list of
|
|
|
|
* Accounts controlled by the given BrainKey
|
|
|
|
*/
|
|
|
|
private fun handleAccountProperties(result: Any?) {
|
|
|
|
if (result is List<*> && result[0] is AccountProperties) {
|
|
|
|
val accountPropertiesList = result as List<AccountProperties>
|
2018-11-23 02:13:10 +00:00
|
|
|
if (accountPropertiesList.size > 1) {
|
|
|
|
val candidates = ArrayList<String>()
|
|
|
|
for (accountProperties in accountPropertiesList) {
|
|
|
|
candidates.add(accountProperties.name)
|
|
|
|
}
|
2019-01-04 22:50:56 +00:00
|
|
|
MaterialDialog(context!!)
|
2018-11-23 02:13:10 +00:00
|
|
|
.title(R.string.dialog__account_candidates_title)
|
|
|
|
.message(R.string.dialog__account_candidates_content)
|
2018-11-24 15:11:57 +00:00
|
|
|
.listItemsSingleChoice (items = candidates, initialSelection = -1) { _, index, _ ->
|
2018-11-23 02:13:10 +00:00
|
|
|
if (index >= 0) {
|
|
|
|
// If one account was selected, we keep a reference to it and
|
|
|
|
// store the account properties
|
|
|
|
mUserAccount = mUserAccountCandidates!![index]
|
2019-01-08 19:27:18 +00:00
|
|
|
onAccountSelected(accountPropertiesList[index], tietPin.text.toString())
|
2018-11-23 02:13:10 +00:00
|
|
|
}
|
|
|
|
}
|
2018-11-24 15:11:57 +00:00
|
|
|
.positiveButton(android.R.string.ok)
|
|
|
|
.negativeButton(android.R.string.cancel) {
|
|
|
|
mKeyReferencesAttempts = 0
|
|
|
|
}
|
|
|
|
.cancelable(false)
|
2018-11-23 02:13:10 +00:00
|
|
|
.show()
|
|
|
|
} else if (accountPropertiesList.size == 1) {
|
2019-01-08 19:27:18 +00:00
|
|
|
onAccountSelected(accountPropertiesList[0], tietPin.text.toString())
|
2018-11-23 02:13:10 +00:00
|
|
|
} else {
|
2019-01-04 22:50:56 +00:00
|
|
|
context?.toast(getString(R.string.error__try_again))
|
2018-11-23 02:13:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-01-11 19:46:50 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Task used to obtain frequent updates on the global dynamic properties object
|
|
|
|
*/
|
|
|
|
private val mRequestDynamicGlobalPropertiesTask = object : Runnable {
|
|
|
|
override fun run() {
|
|
|
|
if (mNetworkService != null) {
|
|
|
|
if (mNetworkService?.isConnected == true) {
|
|
|
|
mNetworkService?.sendMessage(GetDynamicGlobalProperties(), GetDynamicGlobalProperties.REQUIRED_API)
|
|
|
|
} else {
|
|
|
|
Log.d(TAG, "NetworkService exists but is not connected")
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Log.d(TAG, "NetworkService reference is null")
|
|
|
|
}
|
|
|
|
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)
|
|
|
|
}
|
2018-11-21 23:43:51 +00:00
|
|
|
}
|