mirror of
https://github.com/MetaCubeX/ClashMetaForAndroid.git
synced 2024-11-16 04:12:18 +08:00
feat: add intent filters for tasker automation (#119)
This commit is contained in:
parent
ccfcb71565
commit
021939264f
13
README.md
13
README.md
|
@ -47,6 +47,19 @@ Feature of [Clash.Meta](https://github.com/MetaCubeX/Clash.Meta)
|
||||||
./gradlew app:assembleMeta-AlphaRelease
|
./gradlew app:assembleMeta-AlphaRelease
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Automation
|
||||||
|
|
||||||
|
APP package name is `com.github.metacubex.clash.meta`
|
||||||
|
|
||||||
|
- Toggle Clash.Meta service status
|
||||||
|
- Send intent to `com.github.kr328.clash.ExternalControlActivity` with action `com.github.metacubex.clash.meta.action.TOGGLE_CLASH`
|
||||||
|
- Start Clash.Meta service
|
||||||
|
- Send intent to `com.github.kr328.clash.ExternalControlActivity` with action `com.github.metacubex.clash.meta.action.START_CLASH`
|
||||||
|
- Stop Clash.Meta service
|
||||||
|
- Send intent to `com.github.kr328.clash.ExternalControlActivity` with action `com.github.metacubex.clash.meta.action.STOP_CLASH`
|
||||||
|
- Import a profile
|
||||||
|
- URL Scheme `clash://install-config?url=<encoded URI>` or `clashmeta://install-config?url=<encoded URI>`
|
||||||
|
|
||||||
### Kernel Contribution
|
### Kernel Contribution
|
||||||
|
|
||||||
- CMFA uses the kernel from `android-real` branch under `MetaCubeX/Clash.Meta`, which is a merge of the main `Alpha` branch and `android-open`.
|
- CMFA uses the kernel from `android-real` branch under `MetaCubeX/Clash.Meta`, which is a merge of the main `Alpha` branch and `android-open`.
|
||||||
|
|
|
@ -55,9 +55,9 @@
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".ExternalImportActivity"
|
android:name=".ExternalControlActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:label="@string/import_from_file"
|
android:label="@string/external_control_activity"
|
||||||
android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen">
|
android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
@ -69,6 +69,18 @@
|
||||||
<data android:scheme="clashmeta"/>
|
<data android:scheme="clashmeta"/>
|
||||||
<data android:host="install-config"/>
|
<data android:host="install-config"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="com.github.metacubex.clash.meta.action.START_CLASH" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="com.github.metacubex.clash.meta.action.STOP_CLASH" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="com.github.metacubex.clash.meta.action.TOGGLE_CLASH" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".ApkBrokenActivity"
|
android:name=".ApkBrokenActivity"
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
package com.github.kr328.clash
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
import com.github.kr328.clash.common.constants.Intents
|
||||||
|
import com.github.kr328.clash.common.util.intent
|
||||||
|
import com.github.kr328.clash.common.util.setUUID
|
||||||
|
import com.github.kr328.clash.design.MainDesign
|
||||||
|
import com.github.kr328.clash.design.ui.ToastDuration
|
||||||
|
import com.github.kr328.clash.remote.Remote
|
||||||
|
import com.github.kr328.clash.remote.StatusClient
|
||||||
|
import com.github.kr328.clash.service.model.Profile
|
||||||
|
import com.github.kr328.clash.util.startClashService
|
||||||
|
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.launch
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class ExternalControlActivity : Activity(), CoroutineScope by MainScope() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
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 name = uri.getQueryParameter("name") ?: getString(R.string.new_profile)
|
||||||
|
|
||||||
|
create(type, name).also {
|
||||||
|
patch(it, name, url, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
startActivity(PropertiesActivity::class.intent.setUUID(uuid))
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Intents.ACTION_TOGGLE_CLASH -> if(Remote.broadcasts.clashRunning) {
|
||||||
|
stopClash()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
startClash()
|
||||||
|
}
|
||||||
|
|
||||||
|
Intents.ACTION_START_CLASH -> if(!Remote.broadcasts.clashRunning) {
|
||||||
|
startClash()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Toast.makeText(this, R.string.external_control_started, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
Intents.ACTION_STOP_CLASH -> if(Remote.broadcasts.clashRunning) {
|
||||||
|
stopClash()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Toast.makeText(this, R.string.external_control_stopped, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startClash() {
|
||||||
|
// if (currentProfile == null) {
|
||||||
|
// Toast.makeText(this, R.string.no_profile_selected, Toast.LENGTH_LONG).show()
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
val vpnRequest = startClashService()
|
||||||
|
if (vpnRequest != null) {
|
||||||
|
Toast.makeText(this, R.string.unable_to_start_vpn, Toast.LENGTH_LONG).show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Toast.makeText(this, R.string.external_control_started, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun stopClash() {
|
||||||
|
stopClashService()
|
||||||
|
Toast.makeText(this, R.string.external_control_stopped, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,44 +0,0 @@
|
||||||
package com.github.kr328.clash
|
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Bundle
|
|
||||||
import com.github.kr328.clash.common.util.intent
|
|
||||||
import com.github.kr328.clash.common.util.setUUID
|
|
||||||
import com.github.kr328.clash.service.model.Profile
|
|
||||||
import com.github.kr328.clash.util.withProfile
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.MainScope
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class ExternalImportActivity : Activity(), CoroutineScope by MainScope() {
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
|
|
||||||
if (intent.action != Intent.ACTION_VIEW)
|
|
||||||
return finish()
|
|
||||||
|
|
||||||
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 name = uri.getQueryParameter("name") ?: getString(R.string.new_profile)
|
|
||||||
|
|
||||||
create(type, name).also {
|
|
||||||
patch(it, name, url, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
startActivity(PropertiesActivity::class.intent.setUUID(uuid))
|
|
||||||
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,6 +5,9 @@ import com.github.kr328.clash.common.util.packageName
|
||||||
object Intents {
|
object Intents {
|
||||||
// Public
|
// Public
|
||||||
val ACTION_PROVIDE_URL = "$packageName.action.PROVIDE_URL"
|
val ACTION_PROVIDE_URL = "$packageName.action.PROVIDE_URL"
|
||||||
|
val ACTION_START_CLASH = "$packageName.action.START_CLASH"
|
||||||
|
val ACTION_STOP_CLASH = "$packageName.action.STOP_CLASH"
|
||||||
|
val ACTION_TOGGLE_CLASH = "$packageName.action.TOGGLE_CLASH"
|
||||||
|
|
||||||
const val EXTRA_NAME = "name"
|
const val EXTRA_NAME = "name"
|
||||||
|
|
||||||
|
|
|
@ -245,4 +245,7 @@
|
||||||
<string name="geofile_imported">%1$s imported</string>
|
<string name="geofile_imported">%1$s imported</string>
|
||||||
<string name="toast_profile_updated_complete">Update profile %s completed</string>
|
<string name="toast_profile_updated_complete">Update profile %s completed</string>
|
||||||
<string name="toast_profile_updated_failed">Update profile %1$s failed: %2$s</string>
|
<string name="toast_profile_updated_failed">Update profile %1$s failed: %2$s</string>
|
||||||
|
<string name="external_control_activity">External Control</string>
|
||||||
|
<string name="external_control_started">Clash.Meta service started</string>
|
||||||
|
<string name="external_control_stopped">Clash.Meta service stopped</string>
|
||||||
</resources>
|
</resources>
|
|
@ -245,4 +245,7 @@
|
||||||
<string name="geofile_imported">%1$s imported</string>
|
<string name="geofile_imported">%1$s imported</string>
|
||||||
<string name="toast_profile_updated_complete">Update profile %s completed</string>
|
<string name="toast_profile_updated_complete">Update profile %s completed</string>
|
||||||
<string name="toast_profile_updated_failed">Update profile %1$s failed: %2$s</string>
|
<string name="toast_profile_updated_failed">Update profile %1$s failed: %2$s</string>
|
||||||
|
<string name="external_control_activity">External Control</string>
|
||||||
|
<string name="external_control_started">Clash.Meta service started</string>
|
||||||
|
<string name="external_control_stopped">Clash.Meta service stopped</string>
|
||||||
</resources>
|
</resources>
|
|
@ -310,4 +310,7 @@
|
||||||
<string name="geofile_imported">%1$s imported</string>
|
<string name="geofile_imported">%1$s imported</string>
|
||||||
<string name="toast_profile_updated_complete">Update profile %s completed</string>
|
<string name="toast_profile_updated_complete">Update profile %s completed</string>
|
||||||
<string name="toast_profile_updated_failed">Update profile %1$s failed: %2$s</string>
|
<string name="toast_profile_updated_failed">Update profile %1$s failed: %2$s</string>
|
||||||
|
<string name="external_control_activity">External Control</string>
|
||||||
|
<string name="external_control_started">Clash.Meta service started</string>
|
||||||
|
<string name="external_control_stopped">Clash.Meta service stopped</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -242,4 +242,7 @@
|
||||||
<string name="geofile_imported">%1$s imported</string>
|
<string name="geofile_imported">%1$s imported</string>
|
||||||
<string name="toast_profile_updated_complete">Update profile %s completed</string>
|
<string name="toast_profile_updated_complete">Update profile %s completed</string>
|
||||||
<string name="toast_profile_updated_failed">Update profile %1$s failed: %2$s</string>
|
<string name="toast_profile_updated_failed">Update profile %1$s failed: %2$s</string>
|
||||||
|
<string name="external_control_activity">External Control</string>
|
||||||
|
<string name="external_control_started">Clash.Meta service started</string>
|
||||||
|
<string name="external_control_stopped">Clash.Meta service stopped</string>
|
||||||
</resources>
|
</resources>
|
|
@ -242,4 +242,7 @@
|
||||||
<string name="geofile_imported">%1$s imported</string>
|
<string name="geofile_imported">%1$s imported</string>
|
||||||
<string name="toast_profile_updated_complete">Update profile %s completed</string>
|
<string name="toast_profile_updated_complete">Update profile %s completed</string>
|
||||||
<string name="toast_profile_updated_failed">Update profile %1$s failed: %2$s</string>
|
<string name="toast_profile_updated_failed">Update profile %1$s failed: %2$s</string>
|
||||||
|
<string name="external_control_activity">External Control</string>
|
||||||
|
<string name="external_control_started">Clash.Meta service started</string>
|
||||||
|
<string name="external_control_stopped">Clash.Meta service stopped</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -245,4 +245,7 @@
|
||||||
<string name="geofile_imported">%1$s 已导入</string>
|
<string name="geofile_imported">%1$s 已导入</string>
|
||||||
<string name="toast_profile_updated_complete">更新配置 %s 成功</string>
|
<string name="toast_profile_updated_complete">更新配置 %s 成功</string>
|
||||||
<string name="toast_profile_updated_failed">更新配置 %1$s 失败: %2$s</string>
|
<string name="toast_profile_updated_failed">更新配置 %1$s 失败: %2$s</string>
|
||||||
|
<string name="external_control_activity">External Control</string>
|
||||||
|
<string name="external_control_started">Clash.Meta 服务已启动</string>
|
||||||
|
<string name="external_control_stopped">Clash.Meta 服务已停止</string>
|
||||||
</resources>
|
</resources>
|
|
@ -310,4 +310,7 @@
|
||||||
<string name="geofile_imported">%1$s imported</string>
|
<string name="geofile_imported">%1$s imported</string>
|
||||||
<string name="toast_profile_updated_complete">Update profile %s completed</string>
|
<string name="toast_profile_updated_complete">Update profile %s completed</string>
|
||||||
<string name="toast_profile_updated_failed">Update profile %1$s failed: %2$s</string>
|
<string name="toast_profile_updated_failed">Update profile %1$s failed: %2$s</string>
|
||||||
|
<string name="external_control_activity">External Control</string>
|
||||||
|
<string name="external_control_started">Clash.Meta service started</string>
|
||||||
|
<string name="external_control_stopped">Clash.Meta service stopped</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user