x1ongzhu 1 anno fa
parent
commit
bf4e268d12

+ 1 - 1
app/build.gradle

@@ -24,7 +24,7 @@ android {
         applicationId "com.example.modifier"
         minSdk 26
         targetSdk 34
-        versionCode 114
+        versionCode 116
         versionName "1.0.1"
         archivesBaseName = "modifier-${versionCode}"
 

+ 17 - 5
app/schemas/com.example.modifier.data.AppDatabase/2.json

@@ -2,11 +2,11 @@
   "formatVersion": 1,
   "database": {
     "version": 2,
-    "identityHash": "66680df28f89cc498c93ddbc40b7526f",
+    "identityHash": "7b0b95db3e6d99efa35ac7695cd130c6",
     "entities": [
       {
         "tableName": "BackupItem",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `createdAt` TEXT NOT NULL, `number` TEXT NOT NULL, `country` TEXT NOT NULL, `code` TEXT NOT NULL, `mcc` TEXT NOT NULL, `mnc` TEXT NOT NULL, `imei` TEXT NOT NULL, `imsi` TEXT NOT NULL, `iccid` TEXT NOT NULL, `sendCount` INTEGER NOT NULL, `path` TEXT NOT NULL, `lastUse` TEXT NOT NULL DEFAULT 'createdAt')",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `createdAt` INTEGER NOT NULL, `number` TEXT NOT NULL, `country` TEXT NOT NULL, `code` TEXT NOT NULL, `mcc` TEXT NOT NULL, `mnc` TEXT NOT NULL, `imei` TEXT NOT NULL, `imsi` TEXT NOT NULL, `iccid` TEXT NOT NULL, `sendCount` INTEGER NOT NULL, `path` TEXT NOT NULL, `lastUse` INTEGER NOT NULL, `type` TEXT NOT NULL, `fresh` INTEGER NOT NULL DEFAULT 0)",
         "fields": [
           {
             "fieldPath": "id",
@@ -17,7 +17,7 @@
           {
             "fieldPath": "createdAt",
             "columnName": "createdAt",
-            "affinity": "TEXT",
+            "affinity": "INTEGER",
             "notNull": true
           },
           {
@@ -83,9 +83,21 @@
           {
             "fieldPath": "lastUse",
             "columnName": "lastUse",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "type",
+            "columnName": "type",
             "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "fresh",
+            "columnName": "fresh",
+            "affinity": "INTEGER",
             "notNull": true,
-            "defaultValue": "'createdAt'"
+            "defaultValue": "0"
           }
         ],
         "primaryKey": {
@@ -101,7 +113,7 @@
     "views": [],
     "setupQueries": [
       "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
-      "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '66680df28f89cc498c93ddbc40b7526f')"
+      "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '7b0b95db3e6d99efa35ac7695cd130c6')"
     ]
   }
 }

+ 25 - 40
app/src/main/java/com/example/modifier/Global.kt

@@ -104,6 +104,7 @@ object Global {
         Global.telephonyConfig.iccid = telephonyConfig.iccid
         Global.telephonyConfig.imei = telephonyConfig.imei
         Global.telephonyConfig.imsi = telephonyConfig.imsi
+        Global.telephonyConfig.mock = telephonyConfig.mock
 
         try {
             if (suspend == true) {
@@ -359,35 +360,7 @@ object Global {
     }
 
     @JvmStatic
-    fun clearConv() {
-        val context = Utils.getContext()
-        if (context.getSharedPreferences("settings", Context.MODE_PRIVATE)
-                .getBoolean("do_not_clean", false)
-        ) {
-            return
-        }
-        try {
-            val sqlite3 = sqlite3path()
-            val dbDir = copyDB()
-            val dbPath = File(dbDir, "mmssms.db").path
-            suspend(sms = true)
-            Utils.runAsRoot(
-                "$sqlite3 /data/data/com.google.android.apps.messaging/databases/bugle_db \"DELETE FROM conversations;\"",
-                "$sqlite3 /data/data/com.google.android.apps.messaging/databases/bugle_db \"DELETE FROM messages;\"",
-                "cp $dbPath /data/data/com.android.providers.telephony/databases/mmssms.db",
-                "chmod 660 /data/data/com.android.providers.telephony/databases/mmssms.db",
-                "chown radio:radio /data/data/com.android.providers.telephony/databases/mmssms.db",
-                "echo ok"
-            )
-            unsuspend(sms = true)
-        } catch (e: Exception) {
-            e.printStackTrace()
-        }
-    }
-
-
-    @JvmStatic
-    suspend fun clearConv1() {
+    suspend fun clearConv() {
         val context = Utils.getContext()
         if (context.getSharedPreferences("settings", Context.MODE_PRIVATE)
                 .getBoolean("do_not_clean", false)
@@ -416,7 +389,13 @@ object Global {
                     }
                 } else {
                     val dest = File("/data/data/com.android.providers.telephony/$relative")
-                    cmds.add("cp -f ${file.path} ${dest.path}")
+                    cmds.addAll(
+                        listOf(
+                            "cp -f ${file.path} ${dest.path}",
+                            "chmod 660 ${dest.path}",
+                            "chown radio:radio ${dest.path}"
+                        )
+                    )
                 }
             }
             copyToData(providerDir)
@@ -434,13 +413,8 @@ object Global {
     @JvmStatic
     suspend fun resetAll() {
         try {
-            val sqlite3 = sqlite3path()
-            val dbDir = copyDB()
-            val dbPath = File(dbDir, "mmssms.db").path
+            clearConv()
             shellRun(
-                "cp $dbPath /data/data/com.android.providers.telephony/databases/mmssms.db",
-                "chmod 660 /data/data/com.android.providers.telephony/databases/mmssms.db",
-                "chown radio:radio /data/data/com.android.providers.telephony/databases/mmssms.db",
                 CMD_SUSPEND_MESSAGING_APP,
                 CMD_KILL_MESSAGING_APP,
                 CMD_CLEAR_MESSAGING_APP,
@@ -637,7 +611,12 @@ object Global {
 
     @SuppressLint("SdCardPath")
     @JvmStatic
-    suspend fun backup(backupItemDao: BackupItemDao, type: String, sendCount: Int): BackupItem {
+    suspend fun backup(
+        backupItemDao: BackupItemDao,
+        type: String,
+        sendCount: Int,
+        fresh: Boolean = false
+    ): BackupItem {
         clearConv()
 //        ModifierService.instance!!.toggleRcsSwitch(false)
         val context = Utils.getContext()
@@ -699,7 +678,8 @@ object Global {
             path = dest.path,
             sendCount = sendCount,
             lastUse = Date().time,
-            type = type
+            type = type,
+            fresh = fresh
         )
 
         backupItemDao.findBackupForNumber(telephonyConfig.country, telephonyConfig.number)?.let {
@@ -713,7 +693,7 @@ object Global {
     }
 
     @JvmStatic
-    suspend fun restore(backup: BackupItem) {
+    suspend fun restore(backup: BackupItem): Boolean {
         save(
             TelephonyConfig(
                 number = backup.number,
@@ -762,8 +742,13 @@ object Global {
         ModifierService.instance!!.toggleRcsSwitch(false)
         delay(1000)
         ModifierService.instance!!.toggleRcsSwitch(true)
+        var success = false
         ModifierService.instance!!.waitForRcsState(arrayOf(RcsConfigureState.CONFIGURED), 2.minutes)
-        shellRun("am start -a android.intent.action.SENDTO -d sms:+18583199738 --es sms_body \"Test\" --ez exit_on_sent false")
+            .let {
+                success = it == RcsConfigureState.CONFIGURED
+            }
+//        shellRun("am start -a android.intent.action.SENDTO -d sms:+18583199738 --es sms_body \"Test\" --ez exit_on_sent false")
+        return success
     }
 
     @JvmStatic

+ 2 - 2
app/src/main/java/com/example/modifier/adapter/BackupAdapter.kt

@@ -51,8 +51,8 @@ class BackupAdapter(
         holder.binding.tvTime.text =
             SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date(backup.createdAt))
         holder.binding.tvInfo.text = String.format(
-            "MCC: %s, MNC: %s, Country: %s, SendCount: %d",
-            backup.mcc, backup.mnc, backup.country.uppercase(), backup.sendCount
+            "MCC: %s, MNC: %s, Country: %s, SendCount: %d, Fresh: %b",
+            backup.mcc, backup.mnc, backup.country.uppercase(), backup.sendCount, backup.fresh
         )
         holder.binding.btnRestore.setOnClickListener { v: View? ->
             MaterialAlertDialogBuilder(

+ 15 - 1
app/src/main/java/com/example/modifier/data/AppDatabase.kt

@@ -6,11 +6,24 @@ import androidx.room.Database
 import androidx.room.Room
 import androidx.room.RoomDatabase
 import androidx.room.TypeConverters
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+//val MIGRATION_1_2 = object : Migration(1, 2) {
+//    override fun migrate(db: SupportSQLiteDatabase) {
+//        db.execSQL(
+//            "ALTER TABLE BackupItem ADD COLUMN fresh INTEGER NOT NULL DEFAULT 0"
+//        )
+//    }
+//}
 
 @Database(
     entities = [BackupItem::class],
-    version = 1,
+    version = 2,
     exportSchema = true,
+    autoMigrations = [
+        AutoMigration(from = 1, to = 2)
+    ]
 )
 @TypeConverters(Converters::class)
 abstract class AppDatabase : RoomDatabase() {
@@ -25,6 +38,7 @@ abstract class AppDatabase : RoomDatabase() {
             // if the Instance is not null, return it, otherwise create a new database instance.
             return Instance ?: synchronized(this) {
                 Room.databaseBuilder(context, AppDatabase::class.java, "app")
+//                    .addMigrations(MIGRATION_1_2)
                     .build()
                     .also { Instance = it }
             }

+ 3 - 1
app/src/main/java/com/example/modifier/data/BackupItem.kt

@@ -23,5 +23,7 @@ data class BackupItem(
     var sendCount: Int,
     val path: String,
     val lastUse: Long,
-    val type: String
+    val type: String,
+    @ColumnInfo(defaultValue = "0")
+    val fresh: Boolean = false
 )

+ 1 - 1
app/src/main/java/com/example/modifier/data/BackupItemDao.kt

@@ -27,6 +27,6 @@ interface BackupItemDao {
     @Query("SELECT * FROM backupitem WHERE country = :country AND number = :number limit 1")
     suspend fun findBackupForNumber(country: String, number: String): BackupItem?
 
-    @Query("SELECT * FROM backupitem WHERE number != :number AND (sendCount = 0 OR lastUse < :time) order by createdAt limit 1")
+    @Query("SELECT * FROM backupitem WHERE number != :number AND (fresh = 1 OR lastUse < :time) order by createdAt limit 1")
     suspend fun findBackupForRestore(number: String, time: Long): BackupItem?
 }

+ 165 - 151
app/src/main/java/com/example/modifier/service/ModifierService.kt

@@ -306,7 +306,7 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
             if (Global.hasRoot()) {
                 Global.setupSystem()
                 if (Build.MODEL.startsWith("SM-F707") || Build.MODEL.startsWith("SM-F711")) {
-                    Global.killPhoneProcess(force = true)
+                    Global.killPhoneProcess(force = false)
                 }
             }
             preparing.postValue(false)
@@ -776,7 +776,7 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
         binding.btnClean.setOnClickListener {
             binding.btnClean.isEnabled = false
             CoroutineScope(Dispatchers.IO).launch {
-                Global.clearConv1()
+                Global.clearConv()
                 withContext(Dispatchers.Main) {
                     binding.btnClean.isEnabled = true
                 }
@@ -1031,7 +1031,11 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
         }
     }
 
-    private suspend fun requestNumber(reset: Boolean = false, noBackup: Boolean = false) {
+    private suspend fun requestNumber(
+        reset: Boolean = false,
+        noBackup: Boolean = false,
+        fresh: Boolean = false
+    ) {
         val color = ContextCompat.getColorStateList(binding.root.context, R.color.btn_color)
         binding.btnReq.backgroundTintList = color
         if (getSharedPreferences("settings", Context.MODE_PRIVATE)
@@ -1046,182 +1050,192 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
         requesting.postValue(true)
 
         if (Global.telephonyConfig.mock == false) {
-            backup(backupItemDao, "auto", sendCount)
+            backup(
+                backupItemDao = backupItemDao,
+                type = "auto",
+                sendCount = sendCount,
+                fresh = fresh
+            )
         }
 
         var requestSuccess = false
-        if (requestMode == 2 && !noBackup) {
-            val backup = backupItemDao.findBackupForRestore(
-                Global.telephonyConfig.number,
-                System.currentTimeMillis() - 2 * 24 * 60 * 60 * 1000
-            )
-            if (backup != null) {
-                Global.restore(backup)
-                requestSuccess = true
-            }
-        }
 
-        if (!requestSuccess) {
-            withTimeoutOrNull(1.hours) {
-                var needRest = reset
-                while (true) {
-                    delay(200)
-                    try {
-                        if (needRest &&
-                            !getSharedPreferences("settings", Context.MODE_PRIVATE)
-                                .getBoolean("do_not_reset", false)
-                        ) {
-                            reset()
-                            needRest = false
+        withTimeoutOrNull(1.hours) {
+            var needRest = reset
+            while (true) {
+                delay(200)
+                try {
+                    if (requestMode == 2 && !noBackup) {
+                        val backup = backupItemDao.findBackupForRestore(
+                            Global.telephonyConfig.number,
+                            System.currentTimeMillis() - 2 * 24 * 60 * 60 * 1000
+                        )
+                        if (backup != null) {
+                            if (Global.restore(backup)) {
+                                requestSuccess = true
+                                break
+                            } else {
+                                backup(backupItemDao, "auto", 0)
+                                continue
+                            }
                         }
+                    }
 
-                        rcsConfigureState.postValue(RcsConfigureState.NOT_CONFIGURED)
-                        withContext(Dispatchers.Main) {
-                            binding.tvLog.text = "Requesting number..."
-                        }
+                    if (needRest &&
+                        !getSharedPreferences("settings", Context.MODE_PRIVATE)
+                            .getBoolean("do_not_reset", false)
+                    ) {
+                        reset()
+                        needRest = false
+                    }
 
-                        val response = KtorClient.put(
-                            RcsNumberApi()
-                        ) {
-                            contentType(ContentType.Application.Json)
-                            setBody(
-                                RcsNumberRequest(
-                                    deviceId = Utils.getUniqueID(),
-                                    taskId = currentTaskId
-                                )
+                    rcsConfigureState.postValue(RcsConfigureState.NOT_CONFIGURED)
+                    withContext(Dispatchers.Main) {
+                        binding.tvLog.text = "Requesting number..."
+                    }
+
+                    val response = KtorClient.put(
+                        RcsNumberApi()
+                    ) {
+                        contentType(ContentType.Application.Json)
+                        setBody(
+                            RcsNumberRequest(
+                                deviceId = Utils.getUniqueID(),
+                                taskId = currentTaskId
                             )
-                        }
-                        var rcsNumber = response.body<RcsNumberResponse>()
-                        Log.i(TAG, "requestNumber response: $rcsNumber")
+                        )
+                    }
+                    var rcsNumber = response.body<RcsNumberResponse>()
+                    Log.i(TAG, "requestNumber response: $rcsNumber")
 
-                        withContext(Dispatchers.Main) {
-                            binding.tvLog.text = "Requesting success, waiting for logs..."
-                        }
+                    withContext(Dispatchers.Main) {
+                        binding.tvLog.text = "Requesting success, waiting for logs..."
+                    }
 
-                        Global.save(
-                            TelephonyConfig(
-                                rcsNumber.number,
-                                rcsNumber.mcc,
-                                rcsNumber.mnc,
-                                Global.genICCID(rcsNumber.mnc, rcsNumber.areaCode),
-                                rcsNumber.mcc + rcsNumber.mnc + RandomStringUtils.randomNumeric(
-                                    15 - rcsNumber.mcc.length - rcsNumber.mnc.length
-                                ),
-                                Utils.generateIMEI(),
-                                rcsNumber.country,
-                                rcsNumber.areaCode
-                            )
+                    Global.save(
+                        TelephonyConfig(
+                            rcsNumber.number,
+                            rcsNumber.mcc,
+                            rcsNumber.mnc,
+                            Global.genICCID(rcsNumber.mnc, rcsNumber.areaCode),
+                            rcsNumber.mcc + rcsNumber.mnc + RandomStringUtils.randomNumeric(
+                                15 - rcsNumber.mcc.length - rcsNumber.mnc.length
+                            ),
+                            Utils.generateIMEI(),
+                            rcsNumber.country,
+                            rcsNumber.areaCode
                         )
+                    )
 
-                        shellRun(CMD_MESSAGING_APP)
-                        withContext(Dispatchers.Main) {
-                            binding.tvLog.text = "Waiting for logs..."
-                        }
+                    shellRun(CMD_MESSAGING_APP)
+                    withContext(Dispatchers.Main) {
+                        binding.tvLog.text = "Waiting for logs..."
+                    }
 
-                        if (rcsNumber.expiryTime.isBefore(LocalDateTime.now())) {
-                            Log.e(TAG, "RCS number expired, retrying...")
-                            continue
-                        }
-                        var sendOtpTimeout = ChronoUnit.SECONDS.between(
-                            LocalDateTime.now(),
-                            rcsNumber.expiryTime
-                        ).seconds
-                        if (sendOtpTimeout < 60.seconds) {
-                            Log.e(TAG, "OTP timeout too short, retrying...")
-                            continue
-                        }
-                        if (sendOtpTimeout > 2.minutes) {
-                            sendOtpTimeout = 2.minutes
-                        }
-                        if (waitForRcsState(
-                                arrayOf(RcsConfigureState.WAITING_FOR_OTP),
-                                sendOtpTimeout
-                            ) != RcsConfigureState.WAITING_FOR_OTP
-                        ) {
-                            if (!toggleRcsSwitch(true)) {
-                                needRest = true
-                            }
-                            Log.e(TAG, "RCS not entered waiting for OTP state, retrying...")
-                            continue
-                        }
-                        if (rcsNumber.expiryTime.isBefore(LocalDateTime.now())) {
-                            Log.e(TAG, "RCS number expired, retrying...")
-                            continue
+                    if (rcsNumber.expiryTime.isBefore(LocalDateTime.now())) {
+                        Log.e(TAG, "RCS number expired, retrying...")
+                        continue
+                    }
+                    var sendOtpTimeout = ChronoUnit.SECONDS.between(
+                        LocalDateTime.now(),
+                        rcsNumber.expiryTime
+                    ).seconds
+                    if (sendOtpTimeout < 60.seconds) {
+                        Log.e(TAG, "OTP timeout too short, retrying...")
+                        continue
+                    }
+                    if (sendOtpTimeout > 2.minutes) {
+                        sendOtpTimeout = 2.minutes
+                    }
+                    if (waitForRcsState(
+                            arrayOf(RcsConfigureState.WAITING_FOR_OTP),
+                            sendOtpTimeout
+                        ) != RcsConfigureState.WAITING_FOR_OTP
+                    ) {
+                        if (!toggleRcsSwitch(true)) {
+                            needRest = true
                         }
+                        Log.e(TAG, "RCS not entered waiting for OTP state, retrying...")
+                        continue
+                    }
+                    if (rcsNumber.expiryTime.isBefore(LocalDateTime.now())) {
+                        Log.e(TAG, "RCS number expired, retrying...")
+                        continue
+                    }
 
-                        withTimeoutOrNull(60.seconds) {
-                            while (true) {
-                                try {
-                                    rcsNumber = KtorClient.get(RcsNumberApi.Id(id = rcsNumber.id))
-                                        .body<RcsNumberResponse>()
-                                    Log.i(TAG, "wait for otp response: $rcsNumber")
-                                    if (rcsNumber.status == RcsNumberResponse.STATUS_SUCCESS || rcsNumber.status == RcsNumberResponse.STATUS_EXPIRED) {
-                                        break
-                                    }
-                                } catch (exception: Exception) {
-                                    Log.e(TAG, "wait for otp Error: ${exception.stackTrace}")
+                    withTimeoutOrNull(60.seconds) {
+                        while (true) {
+                            try {
+                                rcsNumber = KtorClient.get(RcsNumberApi.Id(id = rcsNumber.id))
+                                    .body<RcsNumberResponse>()
+                                Log.i(TAG, "wait for otp response: $rcsNumber")
+                                if (rcsNumber.status == RcsNumberResponse.STATUS_SUCCESS || rcsNumber.status == RcsNumberResponse.STATUS_EXPIRED) {
+                                    break
                                 }
-                                delay(2.seconds)
+                            } catch (exception: Exception) {
+                                Log.e(TAG, "wait for otp Error: ${exception.stackTrace}")
                             }
+                            delay(2.seconds)
                         }
+                    }
 
-                        if (rcsNumber.status != RcsNumberResponse.STATUS_SUCCESS) {
-                            Log.e(TAG, "OTP not received, retrying...")
-                            continue
-                        }
+                    if (rcsNumber.status != RcsNumberResponse.STATUS_SUCCESS) {
+                        Log.e(TAG, "OTP not received, retrying...")
+                        continue
+                    }
+
+                    val match =
+                        Regex("Your Messenger verification code is G-(\\d{6})")
+                            .matchEntire(rcsNumber.message!!)
+                    if (match != null) {
+                        val otp = match.groupValues[1]
+                        Log.i(TAG, "OTP: $otp")
+                        val sender = "3538"
+                        val msg = "Your Messenger verification code is G-$otp"
+
+                        val configured = run configuring@{
+                            repeat(2) {
+                                Global.sendSmsIntent(sender, msg)
+                                val state =
+                                    waitForRcsState(
+                                        arrayOf(
+                                            RcsConfigureState.CONFIGURED,
+                                            RcsConfigureState.RETRY
+                                        ), 60.seconds
+                                    )
+                                when (state) {
+                                    RcsConfigureState.CONFIGURED -> {
+                                        return@configuring true
+                                    }
 
-                        val match =
-                            Regex("Your Messenger verification code is G-(\\d{6})")
-                                .matchEntire(rcsNumber.message!!)
-                        if (match != null) {
-                            val otp = match.groupValues[1]
-                            Log.i(TAG, "OTP: $otp")
-                            val sender = "3538"
-                            val msg = "Your Messenger verification code is G-$otp"
-
-                            val configured = run configuring@{
-                                repeat(2) {
-                                    Global.sendSmsIntent(sender, msg)
-                                    val state =
+                                    RcsConfigureState.RETRY -> {
                                         waitForRcsState(
-                                            arrayOf(
-                                                RcsConfigureState.CONFIGURED,
-                                                RcsConfigureState.RETRY
-                                            ), 60.seconds
+                                            arrayOf(RcsConfigureState.WAITING_FOR_OTP),
+                                            60.seconds
                                         )
-                                    when (state) {
-                                        RcsConfigureState.CONFIGURED -> {
-                                            return@configuring true
-                                        }
-
-                                        RcsConfigureState.RETRY -> {
-                                            waitForRcsState(
-                                                arrayOf(RcsConfigureState.WAITING_FOR_OTP),
-                                                60.seconds
-                                            )
-                                        }
-
-                                        else -> {
-                                            Log.e(TAG, "verifyOtp fail, retrying...")
-                                        }
+                                    }
+
+                                    else -> {
+                                        Log.e(TAG, "verifyOtp fail, retrying...")
                                     }
                                 }
-                                false
-                            }
-                            if (!configured) {
-                                Log.e(TAG, "RCS not configured, retrying...")
-                                continue
-                            } else {
-                                requestSuccess = true
-                                break
                             }
+                            false
+                        }
+                        if (!configured) {
+                            Log.e(TAG, "RCS not configured, retrying...")
+                            continue
+                        } else {
+                            requestSuccess = true
+                            break
                         }
-                    } catch (e: Exception) {
-                        Log.e(TAG, "requestNumberError: ${e.message}", e)
                     }
+                } catch (e: Exception) {
+                    Log.e(TAG, "requestNumberError: ${e.message}", e)
                 }
             }
         }
+
         requesting.postValue(false)
 
         if (requestSuccess) {
@@ -1299,7 +1313,7 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
 
             checkRcsAvailabilityNumbers.forEach {
                 startActivity(smsIntent(it, ""))
-                val s = withTimeoutOrNull(3.seconds) {
+                val s = withTimeoutOrNull(5.seconds) {
                     while (true) {
                         val root = rootInActiveWindow
                         val traverseResult = TraverseResult()
@@ -1329,7 +1343,7 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
             binding.btnStoreNumbers.isEnabled = false
         }
         repeat(100) {
-            requestNumber()
+            requestNumber(fresh = it > 0)
             delay(5000)
         }
         withContext(Dispatchers.Main) {

+ 9 - 12
app/src/main/java/com/example/modifier/ui/utils/UtilsFragment.kt

@@ -97,18 +97,15 @@ class UtilsFragment : Fragment() {
         binding.btnClearConv.setOnClickListener { v: View? ->
             binding.btnClearConv.isEnabled = false
             Utils.makeLoadingButton(context, binding.btnClearConv)
-            handler.post {
-                executor.execute {
-                    clearConv()
-                    handler.post {
-                        binding.btnClearConv.setIconResource(R.drawable.ic_done)
-                        binding.btnClearConv.text = "OK"
-                        handler.postDelayed({
-                            binding.btnClearConv.isEnabled = true
-                            binding.btnClearConv.icon = null
-                            binding.btnClearConv.text = "Clear Msg"
-                        }, 1500)
-                    }
+            CoroutineScope(Dispatchers.IO).launch {
+                clearConv()
+                withContext(Dispatchers.Main) {
+                    binding.btnClearConv.setIconResource(R.drawable.ic_done)
+                    binding.btnClearConv.text = "OK"
+                    delay(1500L)
+                    binding.btnClearConv.isEnabled = true
+                    binding.btnClearConv.icon = null
+                    binding.btnClearConv.text = "Clear Msg"
                 }
             }
         }