x1ongzhu 1 год назад
Родитель
Сommit
4a9bf384eb

+ 47 - 5
app/src/main/java/com/example/modifier/Global.kt

@@ -1,6 +1,8 @@
 package com.example.modifier
 
 import android.annotation.SuppressLint
+import android.app.AlarmManager
+import android.app.PendingIntent
 import android.content.Context
 import android.content.Intent
 import android.os.Build
@@ -8,11 +10,9 @@ import android.util.Log
 import androidx.core.content.ContextCompat
 import com.example.modifier.data.BackupItem
 import com.example.modifier.data.BackupItemDao
-import com.example.modifier.enums.RcsConfigureState
 import com.example.modifier.http.KtorClient
 import com.example.modifier.model.TelephonyConfig
 import com.example.modifier.serializer.Json
-import com.example.modifier.service.ModifierService
 import com.example.modifier.ui.shellRun
 import com.example.modifier.utils.RcsHackTool
 import com.google.gson.Gson
@@ -26,9 +26,7 @@ import kotlinx.serialization.encodeToString
 import org.apache.commons.io.FileUtils
 import org.apache.commons.io.IOUtils
 import org.apache.commons.lang3.RandomStringUtils
-import org.apache.commons.lang3.StringUtils
 import java.io.File
-import java.io.FileWriter
 import java.nio.file.Files
 import java.time.ZoneId
 import java.time.ZonedDateTime
@@ -36,7 +34,7 @@ import java.time.format.DateTimeFormatter
 import java.util.Base64
 import java.util.Date
 import java.util.Locale
-import kotlin.time.Duration.Companion.minutes
+
 
 object Global {
     @JvmField
@@ -779,4 +777,48 @@ object Global {
             false
         }
     }
+
+    @JvmStatic
+    fun stopClash() {
+        try {
+            val context = Utils.getContext()
+            val intent = Intent()
+            intent.action = "com.github.metacubex.clash.meta.action.STOP_CLASH"
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+            context.startActivity(intent)
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+    }
+
+    @JvmStatic
+    fun changeClashProfile(name: String, base64: String) {
+        try {
+            val context = Utils.getContext()
+            val intent = Intent()
+            intent.action = "com.github.metacubex.clash.meta.action.USE_PROFILE"
+            intent.putExtra("base64", base64)
+            intent.putExtra("name", name)
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+            context.startActivity(intent)
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+    }
+
+    @JvmStatic
+    fun restartModifier(){
+        val context = Utils.getContext()
+        val mStartActivity: Intent = Intent(context, MainActivity::class.java)
+        val mPendingIntentId = 123456
+        val mPendingIntent = PendingIntent.getActivity(
+            context,
+            mPendingIntentId,
+            mStartActivity,
+            PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
+        )
+        val mgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
+        mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent)
+        System.exit(0)
+    }
 }

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

@@ -18,6 +18,7 @@ import android.util.DisplayMetrics
 import android.util.Log
 import android.view.Gravity
 import android.view.LayoutInflater
+import android.view.MenuItem
 import android.view.MotionEvent
 import android.view.View
 import android.view.View.OnTouchListener
@@ -26,6 +27,8 @@ import android.view.accessibility.AccessibilityEvent
 import android.view.accessibility.AccessibilityNodeInfo
 import android.widget.CompoundButton
 import android.widget.FrameLayout
+import androidx.annotation.MenuRes
+import androidx.appcompat.widget.PopupMenu
 import androidx.core.content.ContextCompat
 import androidx.datastore.core.DataStore
 import androidx.datastore.preferences.core.Preferences
@@ -43,8 +46,11 @@ import com.example.modifier.CMD_MESSAGING_APP
 import com.example.modifier.CMD_RCS_SETTINGS_ACTIVITY
 import com.example.modifier.Global
 import com.example.modifier.Global.backup
+import com.example.modifier.Global.changeClashProfile
 import com.example.modifier.Global.load
 import com.example.modifier.Global.resetAll
+import com.example.modifier.Global.restartModifier
+import com.example.modifier.Global.stopClash
 import com.example.modifier.R
 import com.example.modifier.TraverseResult
 import com.example.modifier.Utils
@@ -173,10 +179,8 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
 
     private var sendCount: Int
         get() {
-            return getSharedPreferences(
-                BuildConfig.APPLICATION_ID,
-                MODE_PRIVATE
-            ).getInt("sendCount", 0)
+            return getSharedPreferences(BuildConfig.APPLICATION_ID, MODE_PRIVATE)
+                .getInt("sendCount", 0)
         }
         set(value) {
             getSharedPreferences(BuildConfig.APPLICATION_ID, MODE_PRIVATE).edit()
@@ -185,10 +189,8 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
 
     private var requestNumberCount: Int
         get() {
-            return getSharedPreferences(
-                BuildConfig.APPLICATION_ID,
-                MODE_PRIVATE
-            ).getInt("requestNumberCount", 0)
+            return getSharedPreferences(BuildConfig.APPLICATION_ID, MODE_PRIVATE)
+                .getInt("requestNumberCount", 0)
         }
         set(value) {
             getSharedPreferences(BuildConfig.APPLICATION_ID, MODE_PRIVATE).edit()
@@ -230,24 +232,24 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
                         } else if (line.contains("destState=ReplayRequestState")) {
                             rcsConfigureState.postValue(RcsConfigureState.REPLAY_REQUEST)
                         }
-                        Regex("(?<time>\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}.\\d{3}) I/BugleRcsEngine\\(\\W*\\d+\\): (?<log>.*)").matchEntire(
-                            line
-                        )?.apply {
-                            val time = groups["time"]?.value?.dropLast(4)
-                            val log = groups["log"]?.value
-                                ?.replace(Regex("\\[\\w+-\\w+-\\w+-\\w+-\\w+]"), "")
-                                ?.replace(Regex("\\[CONTEXT.*]"), "")
-                                ?.trim()
-
-                            if (time != null && log != null) {
-                                if (log.contains("destState=")) {
-                                    logs.add("$time: $log")
-                                    emit(logs.joinToString("\n"))
-                                    delay(100)
-                                    emit(logs.joinToString("\n"))
+                        Regex("(?<time>\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}.\\d{3}) I/BugleRcsEngine\\(\\W*\\d+\\): (?<log>.*)")
+                            .matchEntire(line)
+                            ?.apply {
+                                val time = groups["time"]?.value?.dropLast(4)
+                                val log = groups["log"]?.value
+                                    ?.replace(Regex("\\[\\w+-\\w+-\\w+-\\w+-\\w+]"), "")
+                                    ?.replace(Regex("\\[CONTEXT.*]"), "")
+                                    ?.trim()
+
+                                if (time != null && log != null) {
+                                    if (log.contains("destState=")) {
+                                        logs.add("$time: $log")
+                                        emit(logs.joinToString("\n"))
+                                        delay(100)
+                                        emit(logs.joinToString("\n"))
+                                    }
                                 }
                             }
-                        }
                     }
                 }
         } catch (e: Exception) {
@@ -437,6 +439,7 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
                     Log.e(TAG, "runTaskError: ${e.message}", e)
                     fail.add(taskItem.id)
                 }
+                updateCountUI()
             }
             Utils.runAsRoot(CMD_BACK)
             mSocket.emit(
@@ -754,57 +757,66 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
                 }
             }
         }
-        binding.btnCheck.setOnClickListener {
-            CoroutineScope(Dispatchers.IO).launch {
-                checkRcsAvailability()
-            }
-        }
-        binding.btnStoreNumbers.setOnClickListener {
-            CoroutineScope(Dispatchers.IO).launch {
-                storeNumbers()
-            }
+        binding.btnMore.setOnClickListener {
+            showMenu(newContext, binding.btnMore, R.menu.more)
         }
-        binding.btnToggleOn.setOnClickListener {
-            binding.btnToggleOn.isEnabled = false
-            CoroutineScope(Dispatchers.IO).launch {
-                toggleRcsSwitch(true)
-                withContext(Dispatchers.Main) {
-                    binding.btnToggleOn.isEnabled = true
-                }
-            }
+        busy.observeForever {
+            reportDeviceStatues()
         }
-        binding.btnToggleOff.setOnClickListener {
-            binding.btnToggleOff.isEnabled = false
+        updateCountUI()
+    }
+
+    private fun showMenu(context: Context, v: View, @MenuRes menuRes: Int) {
+        val popup = PopupMenu(context, v)
+        popup.menuInflater.inflate(menuRes, popup.menu)
+        popup.setOnMenuItemClickListener { item ->
+            binding.btnMore.isEnabled = false
             CoroutineScope(Dispatchers.IO).launch {
-                toggleRcsSwitch(false)
-                withContext(Dispatchers.Main) {
-                    binding.btnToggleOff.isEnabled = true
+                when (item.itemId) {
+                    R.id.check_availability -> {
+                        checkRcsAvailability()
+                    }
+
+                    R.id.toggle_on -> {
+                        toggleRcsSwitch(true)
+                    }
+
+                    R.id.toggle_off -> {
+                        toggleRcsSwitch(false)
+                    }
+
+                    R.id.clear_conv -> {
+                        Global.clearConv()
+                    }
+
+                    R.id.store_numbers -> {
+                        storeNumbers()
+                    }
+
+                    R.id.change_profile -> {
+
+                    }
+
+                    R.id.restart_modifier -> {
+                        restartModifier()
+                    }
                 }
-            }
-        }
-        binding.btnClean.setOnClickListener {
-            binding.btnClean.isEnabled = false
-            CoroutineScope(Dispatchers.IO).launch {
-                Global.clearConv()
+
                 withContext(Dispatchers.Main) {
-                    binding.btnClean.isEnabled = true
+                    binding.btnMore.isEnabled = true
                 }
             }
+            true
         }
-        binding.btnChangeProfile.setOnClickListener {
-            val intent = Intent()
-            intent.action = "com.github.metacubex.clash.meta.action.USE_PROFILE"
-            intent.putExtra(
-                "base64",
-                "bW9kZTogcnVsZQ0KdW5pZmllZC1kZWxheTogdHJ1ZQ0KcHJveGllczoNCiAgLSB7bmFtZTogbWN0dG1uMG4sIHNlcnZlcjogbGFib3JhdG9yeS5tZXNnaXR5LnRvcCwgcG9ydDogMTUxNjYsIHJlYWxpdHktb3B0czoge3B1YmxpYy1rZXk6IE5XRG9UY3pjU1AtaHhJaGhGUXQ4Sl9tOWpDRzU1NGlnRWFPRnI4MUlTeVEsIHNob3J0LWlkOiAzNDAwMjZjNWU2MGV9LCBjbGllbnQtZmluZ2VycHJpbnQ6IGNocm9tZSwgdHlwZTogdmxlc3MsIHV1aWQ6IGJkZTBjNjRkLTFmNDItNDZlZi1hMjA3LTNkMGFkZWUyOWVlOCwgdGxzOiB0cnVlLCB0Zm86IGZhbHNlLCBza2lwLWNlcnQtdmVyaWZ5OiBmYWxzZSwgc2VydmVybmFtZTogeWFob28uY29tLCBuZXR3b3JrOiB0Y3B9DQogIC0gbmFtZTogdmUNCiAgICB0eXBlOiBzb2NrczUNCiAgICBzZXJ2ZXI6IGdsb2JhbC5pcG1veXUuY29tDQogICAgcG9ydDogMzAwMA0KICAgIHVzZXJuYW1lOiBidXllcmV2ZW50XzE3M18wXzBfMTBfVEVTVDAwMDJfMTVfMQ0KICAgIHBhc3N3b3JkOiAxMjM0NTYNCiAgICBkaWFsZXItcHJveHk6IG1jdHRtbjBuDQpwcm94eS1ncm91cHM6DQogIC0gbmFtZTog6IqC54K56YCJ5oupDQogICAgdHlwZTogc2VsZWN0DQogICAgcHJveGllczoNCiAgICAgIC0gdmUNCnJ1bGVzOg0KICAtIERPTUFJTi1TVUZGSVgsaXpvdW1hLmNvbSxESVJFQ1QNCiAgLSBJUC1DSURSLDQ3Ljk4LjIyNS4yOC8zMixESVJFQ1QNCiAgLSBJUC1DSURSLDguMTQ5LjEyOC4yNTEvMzIsRElSRUNUDQogIC0gRE9NQUlOLVNVRkZJWCxiYWlkdS5jb20sRElSRUNUDQogIC0gRE9NQUlOLVNVRkZJWCxhbGl5dW5jcy5jb20sRElSRUNUDQogIC0gR0VPSVAsQ04sRElSRUNUDQogIC0gTUFUQ0gs6IqC54K56YCJ5oup"
-            )
-            intent.putExtra("name", "ve")
-            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
-            startActivity(intent)
-        }
-        busy.observeForever {
-            reportDeviceStatues()
+        popup.setOnDismissListener {
+            // Respond to popup being dismissed.
         }
+        // Show the popup menu.
+        popup.show()
+    }
+
+    private fun updateCountUI() {
+        binding.tvCount.text = "${sendCount} / ${counter}"
     }
 
     private fun reportDeviceStatues() {
@@ -815,6 +827,7 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
                 val dataObj = JSONObject()
                 dataObj.put("canSend", canSend)
                 dataObj.put("busy", busy.value)
+                dataObj.put("currentCountry", Global.telephonyConfig.country)
                 data.put("data", dataObj)
                 mSocket.emit("message", data)
             } catch (e: JSONException) {
@@ -1076,6 +1089,8 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
                 sendCount = sendCount,
                 fresh = fresh
             )
+        } else {
+            Global.clearConv();
         }
 
         requestNumberCount++
@@ -1096,28 +1111,19 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
                             prefs.edit()
                                 .remove("clash_profile")
                                 .apply()
-                            val intent = Intent()
-                            intent.action = "com.github.metacubex.clash.meta.action.STOP_CLASH"
-                            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
-                            startActivity(intent)
+                            stopClash()
                         } else {
                             val oldProfile = prefs.getString("clash_profile", "")
                             if (oldProfile != device.clashProfile) {
                                 prefs.edit()
                                     .putString("clash_profile", device.clashProfile)
                                     .apply()
-                                val intent = Intent()
-                                intent.action = "com.github.metacubex.clash.meta.action.USE_PROFILE"
-                                intent.putExtra(
-                                    "base64",
-                                    Base64.encodeToString(
+                                changeClashProfile(
+                                    device.pinCountry!!, Base64.encodeToString(
                                         device.clashProfile!!.toByteArray(),
                                         Base64.DEFAULT
                                     )
                                 )
-                                intent.putExtra("name", device.pinCountry)
-                                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
-                                startActivity(intent)
                                 delay(5000)
                             }
                         }
@@ -1404,16 +1410,10 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
     }
 
     private suspend fun storeNumbers() {
-        withContext(Dispatchers.Main) {
-            binding.btnStoreNumbers.isEnabled = false
-        }
         repeat(100) {
             requestNumber(reset = true, fresh = it > 0)
             delay(5000)
         }
-        withContext(Dispatchers.Main) {
-            binding.btnStoreNumbers.isEnabled = true
-        }
     }
 
 }

+ 10 - 0
app/src/main/res/drawable/ic_more_horiz.xml

@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="960"
+    android:viewportHeight="960"
+    android:tint="?attr/colorControlNormal">
+  <path
+      android:fillColor="@android:color/white"
+      android:pathData="M240,560Q207,560 183.5,536.5Q160,513 160,480Q160,447 183.5,423.5Q207,400 240,400Q273,400 296.5,423.5Q320,447 320,480Q320,513 296.5,536.5Q273,560 240,560ZM480,560Q447,560 423.5,536.5Q400,513 400,480Q400,447 423.5,423.5Q447,400 480,400Q513,400 536.5,423.5Q560,447 560,480Q560,513 536.5,536.5Q513,560 480,560ZM720,560Q687,560 663.5,536.5Q640,513 640,480Q640,447 663.5,423.5Q687,400 720,400Q753,400 776.5,423.5Q800,447 800,480Q800,513 776.5,536.5Q753,560 720,560Z"/>
+</vector>

+ 19 - 66
app/src/main/res/layout/floating_window.xml

@@ -106,82 +106,35 @@
                         app:iconGravity="textStart"
                         app:iconPadding="0dp" />
 
-                    <com.google.android.material.button.MaterialButton
-                        android:id="@+id/btn_change_profile"
-                        style="@style/Widget.Material3.Button.TonalButton"
-                        android:layout_width="46dp"
-                        android:layout_height="34dp"
-                        android:layout_marginStart="2dp"
-                        android:layout_marginEnd="2dp"
-                        app:icon="@drawable/ic_rule_settings"
-                        app:iconGravity="textStart"
-                        app:iconPadding="0dp" />
-
-<!--                    <com.google.android.material.button.MaterialButton-->
-<!--                        android:id="@+id/btn_inspect"-->
-<!--                        style="@style/Widget.Material3.Button.TonalButton"-->
-<!--                        android:layout_width="46dp"-->
-<!--                        android:layout_height="34dp"-->
-<!--                        android:layout_marginStart="2dp"-->
-<!--                        android:layout_marginEnd="2dp"-->
-<!--                        app:icon="@drawable/ic_manage_search"-->
-<!--                        app:iconGravity="textStart"-->
-<!--                        app:iconPadding="0dp" />-->
-
-                    <com.google.android.material.button.MaterialButton
-                        android:id="@+id/btn_check"
-                        style="@style/Widget.Material3.Button.TonalButton"
-                        android:layout_width="46dp"
-                        android:layout_height="34dp"
-                        android:layout_marginStart="2dp"
-                        android:layout_marginEnd="2dp"
-                        app:icon="@drawable/ic_ecg_heart"
-                        app:iconGravity="textStart"
-                        app:iconPadding="0dp" />
+                    <!--                    <com.google.android.material.button.MaterialButton-->
+                    <!--                        android:id="@+id/btn_inspect"-->
+                    <!--                        style="@style/Widget.Material3.Button.TonalButton"-->
+                    <!--                        android:layout_width="46dp"-->
+                    <!--                        android:layout_height="34dp"-->
+                    <!--                        android:layout_marginStart="2dp"-->
+                    <!--                        android:layout_marginEnd="2dp"-->
+                    <!--                        app:icon="@drawable/ic_manage_search"-->
+                    <!--                        app:iconGravity="textStart"-->
+                    <!--                        app:iconPadding="0dp" />-->
 
                     <com.google.android.material.button.MaterialButton
-                        android:id="@+id/btn_store_numbers"
+                        android:id="@+id/btn_more"
                         style="@style/Widget.Material3.Button.TonalButton"
                         android:layout_width="46dp"
                         android:layout_height="34dp"
                         android:layout_marginStart="2dp"
                         android:layout_marginEnd="2dp"
-                        app:icon="@drawable/ic_archive"
+                        app:icon="@drawable/ic_more_horiz"
                         app:iconGravity="textStart"
                         app:iconPadding="0dp" />
 
-                    <com.google.android.material.button.MaterialButton
-                        android:id="@+id/btn_toggle_on"
-                        style="@style/Widget.Material3.Button.TonalButton"
-                        android:layout_width="46dp"
-                        android:layout_height="34dp"
-                        android:layout_marginStart="2dp"
-                        android:layout_marginEnd="2dp"
-                        app:icon="@drawable/ic_toggle_on"
-                        app:iconGravity="textStart"
-                        app:iconPadding="0dp" />
-
-                    <com.google.android.material.button.MaterialButton
-                        android:id="@+id/btn_toggle_off"
-                        style="@style/Widget.Material3.Button.TonalButton"
-                        android:layout_width="46dp"
-                        android:layout_height="34dp"
-                        android:layout_marginStart="2dp"
-                        android:layout_marginEnd="2dp"
-                        app:icon="@drawable/ic_toggle_off"
-                        app:iconGravity="textStart"
-                        app:iconPadding="0dp" />
-
-                    <com.google.android.material.button.MaterialButton
-                        android:id="@+id/btn_clean"
-                        style="@style/Widget.Material3.Button.TonalButton"
-                        android:layout_width="46dp"
-                        android:layout_height="34dp"
-                        android:layout_marginStart="2dp"
-                        android:layout_marginEnd="2dp"
-                        app:icon="@drawable/ic_mop"
-                        app:iconGravity="textStart"
-                        app:iconPadding="0dp" />
+                    <TextView
+                        android:id="@+id/tv_count"
+                        android:layout_width="40dp"
+                        android:layout_height="wrap_content"
+                        android:text="32"
+                        android:textAlignment="center"
+                        android:textSize="12sp" />
                 </GridLayout>
             </androidx.constraintlayout.widget.ConstraintLayout>
         </com.google.android.material.card.MaterialCardView>

+ 24 - 0
app/src/main/res/menu/more.xml

@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:id="@+id/check_availability"
+        android:title="检查可用性" />
+    <item
+        android:id="@+id/toggle_on"
+        android:title="开开关" />
+    <item
+        android:id="@+id/toggle_off"
+        android:title="关开关" />
+    <item
+        android:id="@+id/clear_conv"
+        android:title="清对话" />
+    <item
+        android:id="@+id/store_numbers"
+        android:title="存号码" />
+    <item
+        android:id="@+id/change_profile"
+        android:title="换Clash配置" />
+    <item
+        android:id="@+id/restart_modifier"
+        android:title="重启Modifier" />
+</menu>