|
|
@@ -2,9 +2,13 @@ package com.github.kr328.clash
|
|
|
|
|
|
import android.app.Activity
|
|
|
import android.content.Intent
|
|
|
+import android.net.Uri
|
|
|
import android.os.Bundle
|
|
|
+import android.util.Base64
|
|
|
+import android.util.Log
|
|
|
import android.widget.Toast
|
|
|
import androidx.activity.result.contract.ActivityResultContracts
|
|
|
+import androidx.core.content.FileProvider
|
|
|
import com.github.kr328.clash.common.constants.Intents
|
|
|
import com.github.kr328.clash.common.util.intent
|
|
|
import com.github.kr328.clash.common.util.setUUID
|
|
|
@@ -18,25 +22,28 @@ import com.github.kr328.clash.util.stopClashService
|
|
|
import com.github.kr328.clash.util.withProfile
|
|
|
import kotlinx.coroutines.CoroutineScope
|
|
|
import kotlinx.coroutines.MainScope
|
|
|
+import kotlinx.coroutines.delay
|
|
|
import kotlinx.coroutines.launch
|
|
|
+import java.io.File
|
|
|
import java.util.*
|
|
|
|
|
|
class ExternalControlActivity : Activity(), CoroutineScope by MainScope() {
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
|
super.onCreate(savedInstanceState)
|
|
|
|
|
|
- when(intent.action) {
|
|
|
+ when (intent.action) {
|
|
|
Intent.ACTION_VIEW -> {
|
|
|
val uri = intent.data ?: return finish()
|
|
|
val url = uri.getQueryParameter("url") ?: return finish()
|
|
|
|
|
|
launch {
|
|
|
val uuid = withProfile {
|
|
|
- val type = when (uri.getQueryParameter("type")?.lowercase(Locale.getDefault())) {
|
|
|
- "url" -> Profile.Type.Url
|
|
|
- "file" -> Profile.Type.File
|
|
|
- else -> Profile.Type.Url
|
|
|
- }
|
|
|
+ val type =
|
|
|
+ when (uri.getQueryParameter("type")?.lowercase(Locale.getDefault())) {
|
|
|
+ "url" -> Profile.Type.Url
|
|
|
+ "file" -> Profile.Type.File
|
|
|
+ else -> Profile.Type.Url
|
|
|
+ }
|
|
|
val name = uri.getQueryParameter("name") ?: getString(R.string.new_profile)
|
|
|
|
|
|
create(type, name).also {
|
|
|
@@ -48,26 +55,85 @@ class ExternalControlActivity : Activity(), CoroutineScope by MainScope() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- Intents.ACTION_TOGGLE_CLASH -> if(Remote.broadcasts.clashRunning) {
|
|
|
+ Intents.ACTION_TOGGLE_CLASH -> if (Remote.broadcasts.clashRunning) {
|
|
|
stopClash()
|
|
|
- }
|
|
|
- else {
|
|
|
+ } else {
|
|
|
startClash()
|
|
|
}
|
|
|
|
|
|
- Intents.ACTION_START_CLASH -> if(!Remote.broadcasts.clashRunning) {
|
|
|
+ Intents.ACTION_START_CLASH -> if (!Remote.broadcasts.clashRunning) {
|
|
|
startClash()
|
|
|
- }
|
|
|
- else {
|
|
|
+ } else {
|
|
|
Toast.makeText(this, R.string.external_control_started, Toast.LENGTH_LONG).show()
|
|
|
}
|
|
|
|
|
|
- Intents.ACTION_STOP_CLASH -> if(Remote.broadcasts.clashRunning) {
|
|
|
+ Intents.ACTION_STOP_CLASH -> if (Remote.broadcasts.clashRunning) {
|
|
|
stopClash()
|
|
|
- }
|
|
|
- else {
|
|
|
+ } else {
|
|
|
Toast.makeText(this, R.string.external_control_stopped, Toast.LENGTH_LONG).show()
|
|
|
}
|
|
|
+
|
|
|
+ Intents.ACTION_USE_PROFILE -> {
|
|
|
+ Log.i("ExternalControl", "action=${Intents.ACTION_USE_PROFILE}")
|
|
|
+
|
|
|
+ val base64 = intent.getStringExtra("base64")
|
|
|
+ val name = intent.getStringExtra("name")
|
|
|
+
|
|
|
+ if (base64 == null) {
|
|
|
+ Log.e("ExternalControl", "base64 is null")
|
|
|
+ return finish()
|
|
|
+ }
|
|
|
+ Log.i("ExternalControl", "base64=${base64}")
|
|
|
+ Log.i(
|
|
|
+ "ExternalControl",
|
|
|
+ "base64Decoded=${String(Base64.decode(base64, Base64.DEFAULT))}"
|
|
|
+ )
|
|
|
+
|
|
|
+ if (name == null) {
|
|
|
+ Log.e("ExternalControl", "name is null")
|
|
|
+ return finish()
|
|
|
+ }
|
|
|
+ Log.i("ExternalControl", "name=${name}")
|
|
|
+
|
|
|
+ val dir = File(filesDir, "external_control")
|
|
|
+ if (!dir.exists()) {
|
|
|
+ dir.mkdirs()
|
|
|
+ }
|
|
|
+ val tmpFile = File.createTempFile("clash", ".yaml", dir)
|
|
|
+ tmpFile.writeBytes(Base64.decode(base64, Base64.DEFAULT))
|
|
|
+ val fileUri: Uri? =
|
|
|
+ FileProvider.getUriForFile(
|
|
|
+ this,
|
|
|
+ "com.github.metacubex.clash.myfileprovider",
|
|
|
+ tmpFile
|
|
|
+ )
|
|
|
+ Log.i("ExternalControl", "fileUri=${fileUri}")
|
|
|
+
|
|
|
+ launch {
|
|
|
+ val uuid = withProfile {
|
|
|
+ val type = Profile.Type.Url
|
|
|
+
|
|
|
+ queryAll().forEach {
|
|
|
+ delete(it.uuid)
|
|
|
+ }
|
|
|
+
|
|
|
+ create(type, name).also {
|
|
|
+ patch(it, name, fileUri.toString(), 0)
|
|
|
+ commit(it)
|
|
|
+ stopClashService()
|
|
|
+ queryByUUID(it)?.also { profile ->
|
|
|
+ setActive(profile)
|
|
|
+ }
|
|
|
+ startClashService()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ val res = Intent()
|
|
|
+ res.putExtra(Intents.EXTRA_UUID, uuid)
|
|
|
+ setResult(RESULT_OK, res)
|
|
|
+ delay(5000)
|
|
|
+ finish()
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
return finish()
|
|
|
}
|