forked from shihaam/thijooree
remove logcat
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
package sh.sar.basedbank.api.mib
|
package sh.sar.basedbank.api.mib
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import okhttp3.FormBody
|
import okhttp3.FormBody
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
@@ -40,7 +39,6 @@ class MibContactsClient {
|
|||||||
.build()
|
.build()
|
||||||
|
|
||||||
return client.newCall(request).execute().use { response ->
|
return client.newCall(request).execute().use { response ->
|
||||||
Log.d(TAG, "getCategories: HTTP ${response.code}")
|
|
||||||
if (!response.isSuccessful) return emptyList()
|
if (!response.isSuccessful) return emptyList()
|
||||||
parseCategories(response.body?.string() ?: return emptyList())
|
parseCategories(response.body?.string() ?: return emptyList())
|
||||||
}
|
}
|
||||||
@@ -58,7 +56,6 @@ class MibContactsClient {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "parseCategories error: $e")
|
|
||||||
emptyList()
|
emptyList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,7 +86,6 @@ class MibContactsClient {
|
|||||||
.build()
|
.build()
|
||||||
|
|
||||||
val (contacts, totalCount) = client.newCall(request).execute().use { response ->
|
val (contacts, totalCount) = client.newCall(request).execute().use { response ->
|
||||||
Log.d(TAG, "fetchContacts page $page: HTTP ${response.code}")
|
|
||||||
if (!response.isSuccessful) return all
|
if (!response.isSuccessful) return all
|
||||||
parseContacts(response.body?.string() ?: return all)
|
parseContacts(response.body?.string() ?: return all)
|
||||||
}
|
}
|
||||||
@@ -97,7 +93,6 @@ class MibContactsClient {
|
|||||||
if (all.size >= totalCount || contacts.isEmpty()) break
|
if (all.size >= totalCount || contacts.isEmpty()) break
|
||||||
page++
|
page++
|
||||||
}
|
}
|
||||||
Log.d(TAG, "fetchContacts: loaded ${all.size} contacts")
|
|
||||||
return all
|
return all
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +122,6 @@ class MibContactsClient {
|
|||||||
}
|
}
|
||||||
Pair(contacts, totalCount)
|
Pair(contacts, totalCount)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "parseContacts error: $e")
|
|
||||||
Pair(emptyList(), 0)
|
Pair(emptyList(), 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package sh.sar.basedbank.api.mib
|
package sh.sar.basedbank.api.mib
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
@@ -35,7 +34,6 @@ class MibFinancingClient {
|
|||||||
.build()
|
.build()
|
||||||
|
|
||||||
val html = client.newCall(request).execute().use { response ->
|
val html = client.newCall(request).execute().use { response ->
|
||||||
Log.d(TAG, "fetchFinancing: HTTP ${response.code}")
|
|
||||||
if (!response.isSuccessful) return emptyList()
|
if (!response.isSuccessful) return emptyList()
|
||||||
response.body?.string() ?: return emptyList()
|
response.body?.string() ?: return emptyList()
|
||||||
}
|
}
|
||||||
@@ -69,7 +67,7 @@ class MibFinancingClient {
|
|||||||
lastPayAmount = attrs["lastPayAmount"]?.toDoubleOrNull() ?: 0.0,
|
lastPayAmount = attrs["lastPayAmount"]?.toDoubleOrNull() ?: 0.0,
|
||||||
currency = attrs["curCodeDesc"] ?: "MVR"
|
currency = attrs["curCodeDesc"] ?: "MVR"
|
||||||
)
|
)
|
||||||
}.toList().also { Log.d(TAG, "parsed ${it.size} financing deals") }
|
}.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package sh.sar.basedbank.api.mib
|
package sh.sar.basedbank.api.mib
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import okhttp3.FormBody
|
import okhttp3.FormBody
|
||||||
import sh.sar.basedbank.util.Totp
|
import sh.sar.basedbank.util.Totp
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
@@ -48,16 +47,12 @@ class MibLoginFlow(private val prefs: android.content.SharedPreferences) {
|
|||||||
*/
|
*/
|
||||||
fun login(username: String, passwordHash: String, otpSeed: String): List<MibAccount> {
|
fun login(username: String, passwordHash: String, otpSeed: String): List<MibAccount> {
|
||||||
val appId = getOrCreateAppId()
|
val appId = getOrCreateAppId()
|
||||||
Log.d(TAG, "login: appId=$appId")
|
|
||||||
val key1 = prefs.getString("mib_key1_$username", null)
|
val key1 = prefs.getString("mib_key1_$username", null)
|
||||||
val key2 = prefs.getString("mib_key2_$username", null)
|
val key2 = prefs.getString("mib_key2_$username", null)
|
||||||
Log.d(TAG, "login: stored keys present=${key1 != null && key2 != null}")
|
|
||||||
|
|
||||||
return if (key1 != null && key2 != null) {
|
return if (key1 != null && key2 != null) {
|
||||||
Log.d(TAG, "login: taking regular login path")
|
|
||||||
regularLogin(username, passwordHash, appId, key1, key2)
|
regularLogin(username, passwordHash, appId, key1, key2)
|
||||||
} else {
|
} else {
|
||||||
Log.d(TAG, "login: taking first-time registration path")
|
|
||||||
firstTimeRegistration(username, passwordHash, otpSeed, appId)
|
firstTimeRegistration(username, passwordHash, otpSeed, appId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,40 +62,29 @@ class MibLoginFlow(private val prefs: android.content.SharedPreferences) {
|
|||||||
private fun firstTimeRegistration(
|
private fun firstTimeRegistration(
|
||||||
username: String, passwordHash: String, otpSeed: String, appId: String
|
username: String, passwordHash: String, otpSeed: String, appId: String
|
||||||
): List<MibAccount> {
|
): List<MibAccount> {
|
||||||
Log.d(TAG, "[reg] step 0: key exchange (sfunc=r)")
|
|
||||||
val (session1, _) = initialKeyExchange(appId, MibCrypto.DEFAULT_KEY, "r")
|
val (session1, _) = initialKeyExchange(appId, MibCrypto.DEFAULT_KEY, "r")
|
||||||
Log.d(TAG, "[reg] step 0 done: xxid=${session1.xxid}")
|
|
||||||
|
|
||||||
Log.d(TAG, "[reg] step 1: getAuthType (A44)")
|
|
||||||
val userSalt = getAuthType(session1, username)
|
val userSalt = getAuthType(session1, username)
|
||||||
Log.d(TAG, "[reg] step 1 done: userSalt length=${userSalt.length}")
|
|
||||||
|
|
||||||
Log.d(TAG, "[reg] step 2: registration init (C41)")
|
|
||||||
Log.d(TAG, "[reg] username='$username' userSalt='$userSalt'")
|
|
||||||
val clientSalt = randomAlpha(32)
|
val clientSalt = randomAlpha(32)
|
||||||
val pgf03 = computePgf03(passwordHash, userSalt, clientSalt)
|
val pgf03 = computePgf03(passwordHash, userSalt, clientSalt)
|
||||||
Log.d(TAG, "[reg] pgf03=$pgf03")
|
|
||||||
val regInitPayload = baseData(session1, "C41").apply {
|
val regInitPayload = baseData(session1, "C41").apply {
|
||||||
put("uname", username)
|
put("uname", username)
|
||||||
put("pgf03", pgf03)
|
put("pgf03", pgf03)
|
||||||
put("clientSalt", clientSalt)
|
put("clientSalt", clientSalt)
|
||||||
}
|
}
|
||||||
val regInitResp = doRequest(session1, regInitPayload, "n")
|
val regInitResp = doRequest(session1, regInitPayload, "n")
|
||||||
Log.d(TAG, "[reg] step 2 response: $regInitResp")
|
|
||||||
check(regInitResp.optBoolean("success", false)) {
|
check(regInitResp.optBoolean("success", false)) {
|
||||||
regInitResp.optString("reasonText", "Registration init failed")
|
regInitResp.optString("reasonText", "Registration init failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d(TAG, "[reg] step 3: OTP verify (C42)")
|
|
||||||
val otp = generateOtp(otpSeed)
|
val otp = generateOtp(otpSeed)
|
||||||
Log.d(TAG, "[reg] generated OTP=$otp")
|
|
||||||
val otpPayload = baseData(session1, "C42").apply {
|
val otpPayload = baseData(session1, "C42").apply {
|
||||||
put("otp", otp)
|
put("otp", otp)
|
||||||
put("uname", username)
|
put("uname", username)
|
||||||
put("otpType", "3")
|
put("otpType", "3")
|
||||||
}
|
}
|
||||||
val otpResp = doRequest(session1, otpPayload, "n")
|
val otpResp = doRequest(session1, otpPayload, "n")
|
||||||
Log.d(TAG, "[reg] step 3 response: $otpResp")
|
|
||||||
check(otpResp.optBoolean("success", false)) {
|
check(otpResp.optBoolean("success", false)) {
|
||||||
otpResp.optString("reasonText", "OTP verification failed")
|
otpResp.optString("reasonText", "OTP verification failed")
|
||||||
}
|
}
|
||||||
@@ -108,7 +92,6 @@ class MibLoginFlow(private val prefs: android.content.SharedPreferences) {
|
|||||||
val keyData = otpResp.getJSONArray("data").getJSONObject(0)
|
val keyData = otpResp.getJSONArray("data").getJSONObject(0)
|
||||||
val key1 = keyData.getString("key1")
|
val key1 = keyData.getString("key1")
|
||||||
val key2 = keyData.getString("key2")
|
val key2 = keyData.getString("key2")
|
||||||
Log.d(TAG, "[reg] stored key1/key2 for user=$username")
|
|
||||||
prefs.edit().putString("mib_key1_$username", key1).putString("mib_key2_$username", key2).apply()
|
prefs.edit().putString("mib_key1_$username", key1).putString("mib_key2_$username", key2).apply()
|
||||||
|
|
||||||
return regularLogin(username, passwordHash, appId, key1, key2)
|
return regularLogin(username, passwordHash, appId, key1, key2)
|
||||||
@@ -120,18 +103,12 @@ class MibLoginFlow(private val prefs: android.content.SharedPreferences) {
|
|||||||
username: String, passwordHash: String,
|
username: String, passwordHash: String,
|
||||||
appId: String, key1: String, key2: String
|
appId: String, key1: String, key2: String
|
||||||
): List<MibAccount> {
|
): List<MibAccount> {
|
||||||
Log.d(TAG, "[login] step 4: key exchange (sfunc=i)")
|
|
||||||
val (session2, _) = initialKeyExchange(appId, key1, "i", key2)
|
val (session2, _) = initialKeyExchange(appId, key1, "i", key2)
|
||||||
Log.d(TAG, "[login] step 4 done: xxid=${session2.xxid}")
|
|
||||||
|
|
||||||
Log.d(TAG, "[login] step 5: getAuthType (A44)")
|
|
||||||
val userSalt = getAuthType(session2, username)
|
val userSalt = getAuthType(session2, username)
|
||||||
Log.d(TAG, "[login] step 5 done: userSalt length=${userSalt.length}")
|
|
||||||
|
|
||||||
Log.d(TAG, "[login] step 6: login init (A41)")
|
|
||||||
val clientSalt = randomAlpha(32)
|
val clientSalt = randomAlpha(32)
|
||||||
val pgf03 = computePgf03(passwordHash, userSalt, clientSalt)
|
val pgf03 = computePgf03(passwordHash, userSalt, clientSalt)
|
||||||
Log.d(TAG, "[login] pgf03 length=${pgf03.length}")
|
|
||||||
val loginPayload = baseData(session2, "A41").apply {
|
val loginPayload = baseData(session2, "A41").apply {
|
||||||
put("uname", username)
|
put("uname", username)
|
||||||
put("pgf03", pgf03)
|
put("pgf03", pgf03)
|
||||||
@@ -140,17 +117,14 @@ class MibLoginFlow(private val prefs: android.content.SharedPreferences) {
|
|||||||
put("requireBankData", 1)
|
put("requireBankData", 1)
|
||||||
}
|
}
|
||||||
val loginResp = doRequest(session2, loginPayload, "n")
|
val loginResp = doRequest(session2, loginPayload, "n")
|
||||||
Log.d(TAG, "[login] step 6 response: success=${loginResp.optBoolean("success")} reasonCode=${loginResp.optString("reasonCode")} reasonText=${loginResp.optString("reasonText")}")
|
|
||||||
check(loginResp.optBoolean("success", false)) {
|
check(loginResp.optBoolean("success", false)) {
|
||||||
loginResp.optString("reasonText", "Login init failed")
|
loginResp.optString("reasonText", "Login init failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
val profiles = parseProfiles(loginResp)
|
val profiles = parseProfiles(loginResp)
|
||||||
Log.d(TAG, "[login] parsed ${profiles.size} profiles")
|
|
||||||
|
|
||||||
lastSession = session2
|
lastSession = session2
|
||||||
lastProfiles = profiles
|
lastProfiles = profiles
|
||||||
Log.d(TAG, "[login] step 7: fetch all profiles")
|
|
||||||
return fetchAllProfiles(session2, profiles)
|
return fetchAllProfiles(session2, profiles)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,9 +149,7 @@ class MibLoginFlow(private val prefs: android.content.SharedPreferences) {
|
|||||||
.build()
|
.build()
|
||||||
|
|
||||||
val response = post(formBody)
|
val response = post(formBody)
|
||||||
Log.d(TAG, "keyExchange($sfunc) raw response (first 80): ${response.take(80)}")
|
|
||||||
val respJson = MibCrypto.decrypt(response, encKey)
|
val respJson = MibCrypto.decrypt(response, encKey)
|
||||||
Log.d(TAG, "keyExchange($sfunc) decrypted: success=${respJson.optBoolean("success")} reasonText=${respJson.optString("reasonText")}")
|
|
||||||
|
|
||||||
check(respJson.optBoolean("success", false)) {
|
check(respJson.optBoolean("success", false)) {
|
||||||
respJson.optString("reasonText", "Key exchange failed")
|
respJson.optString("reasonText", "Key exchange failed")
|
||||||
@@ -201,7 +173,6 @@ class MibLoginFlow(private val prefs: android.content.SharedPreferences) {
|
|||||||
|
|
||||||
private fun doRequest(session: MibSession, data: JSONObject, sfunc: String): JSONObject {
|
private fun doRequest(session: MibSession, data: JSONObject, sfunc: String): JSONObject {
|
||||||
val routePath = data.optString("routePath", "?")
|
val routePath = data.optString("routePath", "?")
|
||||||
Log.d(TAG, "doRequest: routePath=$routePath xxid=${session.xxid.take(16)}...")
|
|
||||||
val encrypted = MibCrypto.encrypt(data, session.sessionKey)
|
val encrypted = MibCrypto.encrypt(data, session.sessionKey)
|
||||||
val formBody = FormBody.Builder()
|
val formBody = FormBody.Builder()
|
||||||
.add("xxid", session.xxid)
|
.add("xxid", session.xxid)
|
||||||
@@ -209,9 +180,7 @@ class MibLoginFlow(private val prefs: android.content.SharedPreferences) {
|
|||||||
.add("data", encrypted)
|
.add("data", encrypted)
|
||||||
.build()
|
.build()
|
||||||
val response = post(formBody)
|
val response = post(formBody)
|
||||||
Log.d(TAG, "doRequest($routePath) raw response (first 80): ${response.take(80)}")
|
|
||||||
val result = MibCrypto.decrypt(response, session.sessionKey)
|
val result = MibCrypto.decrypt(response, session.sessionKey)
|
||||||
Log.d(TAG, "doRequest($routePath) decrypted: success=${result.optBoolean("success")} reasonText=${result.optString("reasonText")}")
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,7 +197,6 @@ class MibLoginFlow(private val prefs: android.content.SharedPreferences) {
|
|||||||
* subsequent WebView requests run under that profile.
|
* subsequent WebView requests run under that profile.
|
||||||
*/
|
*/
|
||||||
fun switchProfile(session: MibSession, profile: MibProfile) {
|
fun switchProfile(session: MibSession, profile: MibProfile) {
|
||||||
Log.d(TAG, "switchProfile: profileId=${profile.profileId} cifType=${profile.cifType}")
|
|
||||||
val payload = baseData(session, "P47").apply {
|
val payload = baseData(session, "P47").apply {
|
||||||
put("profileType", profile.profileType)
|
put("profileType", profile.profileType)
|
||||||
put("profileId", profile.profileId)
|
put("profileId", profile.profileId)
|
||||||
@@ -245,7 +213,6 @@ class MibLoginFlow(private val prefs: android.content.SharedPreferences) {
|
|||||||
}
|
}
|
||||||
val resp = doRequest(session, payload, "n")
|
val resp = doRequest(session, payload, "n")
|
||||||
if (!resp.optBoolean("success", false)) {
|
if (!resp.optBoolean("success", false)) {
|
||||||
Log.w(TAG, "P47 failed for profile ${profile.name}: ${resp.optString("reasonText")}")
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
val accountBalances = resp.optJSONArray("accountBalance") ?: continue
|
val accountBalances = resp.optJSONArray("accountBalance") ?: continue
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package sh.sar.basedbank.api.mib
|
package sh.sar.basedbank.api.mib
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import okhttp3.FormBody
|
import okhttp3.FormBody
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
@@ -65,7 +64,6 @@ class MibTransferClient {
|
|||||||
.build()
|
.build()
|
||||||
|
|
||||||
return client.newCall(request).execute().use { response ->
|
return client.newCall(request).execute().use { response ->
|
||||||
Log.d(TAG, "lookupIpsAccount: HTTP ${response.code}")
|
|
||||||
val bodyStr = response.body?.string() ?: ""
|
val bodyStr = response.body?.string() ?: ""
|
||||||
val json = try { JSONObject(bodyStr) } catch (_: Exception) { null }
|
val json = try { JSONObject(bodyStr) } catch (_: Exception) { null }
|
||||||
if (!response.isSuccessful || json == null || !json.optBoolean("success")) {
|
if (!response.isSuccessful || json == null || !json.optBoolean("success")) {
|
||||||
@@ -92,7 +90,6 @@ class MibTransferClient {
|
|||||||
.build()
|
.build()
|
||||||
|
|
||||||
return client.newCall(request).execute().use { response ->
|
return client.newCall(request).execute().use { response ->
|
||||||
Log.d(TAG, "lookupAccountName: HTTP ${response.code}")
|
|
||||||
val bodyStr = response.body?.string() ?: ""
|
val bodyStr = response.body?.string() ?: ""
|
||||||
val json = try { JSONObject(bodyStr) } catch (_: Exception) { null }
|
val json = try { JSONObject(bodyStr) } catch (_: Exception) { null }
|
||||||
if (!response.isSuccessful || json == null || !json.optBoolean("success")) {
|
if (!response.isSuccessful || json == null || !json.optBoolean("success")) {
|
||||||
@@ -122,7 +119,6 @@ class MibTransferClient {
|
|||||||
.build()
|
.build()
|
||||||
|
|
||||||
return client.newCall(request).execute().use { response ->
|
return client.newCall(request).execute().use { response ->
|
||||||
Log.d(TAG, "lookupAlias: HTTP ${response.code}")
|
|
||||||
val bodyStr = response.body?.string() ?: ""
|
val bodyStr = response.body?.string() ?: ""
|
||||||
val json = try { JSONObject(bodyStr) } catch (_: Exception) { null }
|
val json = try { JSONObject(bodyStr) } catch (_: Exception) { null }
|
||||||
if (!response.isSuccessful || json == null || !json.optBoolean("success")) {
|
if (!response.isSuccessful || json == null || !json.optBoolean("success")) {
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import android.os.Handler
|
|||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.TextWatcher
|
import android.text.TextWatcher
|
||||||
import android.util.Log
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -87,10 +86,8 @@ class CredentialsFragment : Fragment() {
|
|||||||
val password = binding.etPassword.text.toString()
|
val password = binding.etPassword.text.toString()
|
||||||
val otpSeed = binding.etOtpSeed.text.toString().trim()
|
val otpSeed = binding.etOtpSeed.text.toString().trim()
|
||||||
|
|
||||||
Log.d(TAG, "Login button pressed for username=$username")
|
|
||||||
|
|
||||||
if (username.isEmpty() || password.isEmpty() || otpSeed.isEmpty()) {
|
if (username.isEmpty() || password.isEmpty() || otpSeed.isEmpty()) {
|
||||||
Log.w(TAG, "Validation failed: empty fields")
|
|
||||||
binding.tvError.text = "Please fill in all fields"
|
binding.tvError.text = "Please fill in all fields"
|
||||||
binding.tvError.visibility = View.VISIBLE
|
binding.tvError.visibility = View.VISIBLE
|
||||||
return
|
return
|
||||||
@@ -106,11 +103,9 @@ class CredentialsFragment : Fragment() {
|
|||||||
|
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
try {
|
try {
|
||||||
Log.d(TAG, "Starting login flow on IO dispatcher")
|
|
||||||
val accounts = withContext(Dispatchers.IO) {
|
val accounts = withContext(Dispatchers.IO) {
|
||||||
flow.login(username, passwordHash, otpSeed)
|
flow.login(username, passwordHash, otpSeed)
|
||||||
}
|
}
|
||||||
Log.d(TAG, "Login succeeded, got ${accounts.size} accounts")
|
|
||||||
CredentialStore(requireContext()).saveMibCredentials(username, passwordHash, otpSeed)
|
CredentialStore(requireContext()).saveMibCredentials(username, passwordHash, otpSeed)
|
||||||
AccountCache.save(requireContext(), accounts)
|
AccountCache.save(requireContext(), accounts)
|
||||||
val app = requireActivity().application as BasedBankApp
|
val app = requireActivity().application as BasedBankApp
|
||||||
@@ -121,7 +116,6 @@ class CredentialsFragment : Fragment() {
|
|||||||
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
|
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "Login failed: ${e.message}", e)
|
|
||||||
binding.tvError.text = e.message ?: "Login failed"
|
binding.tvError.text = e.message ?: "Login failed"
|
||||||
binding.tvError.visibility = View.VISIBLE
|
binding.tvError.visibility = View.VISIBLE
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
Reference in New Issue
Block a user