mirror of
https://github.com/MatsuriDayo/NekoBoxForAndroid.git
synced 2025-12-19 22:50:05 +08:00
improve selector
This commit is contained in:
parent
bb51a38474
commit
1f04d35e94
@ -16,6 +16,7 @@
|
|||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
|
|
||||||
<uses-permission
|
<uses-permission
|
||||||
android:name="android.permission.QUERY_ALL_PACKAGES"
|
android:name="android.permission.QUERY_ALL_PACKAGES"
|
||||||
|
|||||||
@ -149,23 +149,14 @@ class BaseService {
|
|||||||
stopRunner(false, (this as Context).getString(R.string.profile_empty))
|
stopRunner(false, (this as Context).getString(R.string.profile_empty))
|
||||||
}
|
}
|
||||||
if (canReloadSelector()) {
|
if (canReloadSelector()) {
|
||||||
var tag = ""
|
val ent = SagerDatabase.proxyDao.getById(DataStore.selectedProxy)
|
||||||
var ent: ProxyEntity? = null
|
val tag = data.proxy!!.config.profileTagMap[ent?.id] ?: ""
|
||||||
data.proxy!!.config.trafficMap.forEach { (t, list) ->
|
|
||||||
for (it in list) {
|
|
||||||
if (it.id == DataStore.selectedProxy) {
|
|
||||||
ent = it
|
|
||||||
tag = t
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tag.isNotBlank() && ent != null) {
|
if (tag.isNotBlank() && ent != null) {
|
||||||
val success = data.proxy!!.box.selectOutbound(tag)
|
val success = data.proxy!!.box.selectOutbound(tag)
|
||||||
Logs.d("selectOutbound $tag $success")
|
Logs.d("selectOutbound $tag $success")
|
||||||
runOnDefaultDispatcher {
|
runOnDefaultDispatcher {
|
||||||
data.binder.broadcast {
|
data.binder.broadcast {
|
||||||
it.stateChanged(-1, ent!!.displayName(), null)
|
it.stateChanged(-1, ent.displayName(), null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,6 +12,7 @@ class ProxyInstance(profile: ProxyEntity, var service: BaseService.Interface? =
|
|||||||
BoxInstance(profile) {
|
BoxInstance(profile) {
|
||||||
|
|
||||||
var lastSelectorGroupId = -1L
|
var lastSelectorGroupId = -1L
|
||||||
|
var notTmp = true
|
||||||
|
|
||||||
// for TrafficLooper
|
// for TrafficLooper
|
||||||
private var looper: TrafficLooper? = null
|
private var looper: TrafficLooper? = null
|
||||||
@ -20,12 +21,13 @@ class ProxyInstance(profile: ProxyEntity, var service: BaseService.Interface? =
|
|||||||
super.buildConfig()
|
super.buildConfig()
|
||||||
lastSelectorGroupId = super.config.selectorGroupId
|
lastSelectorGroupId = super.config.selectorGroupId
|
||||||
//
|
//
|
||||||
Logs.d(config.config)
|
if (notTmp) Logs.d(config.config)
|
||||||
if (BuildConfig.DEBUG) Logs.d(JavaUtil.gson.toJson(config.trafficMap))
|
if (notTmp && BuildConfig.DEBUG) Logs.d(JavaUtil.gson.toJson(config.trafficMap))
|
||||||
}
|
}
|
||||||
|
|
||||||
// only use this in temporary instance
|
// only use this in temporary instance
|
||||||
fun buildConfigTmp() {
|
fun buildConfigTmp() {
|
||||||
|
notTmp = false
|
||||||
buildConfig()
|
buildConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import io.nekohasekai.sagernet.aidl.TrafficData
|
|||||||
import io.nekohasekai.sagernet.bg.BaseService
|
import io.nekohasekai.sagernet.bg.BaseService
|
||||||
import io.nekohasekai.sagernet.database.DataStore
|
import io.nekohasekai.sagernet.database.DataStore
|
||||||
import io.nekohasekai.sagernet.database.ProfileManager
|
import io.nekohasekai.sagernet.database.ProfileManager
|
||||||
|
import io.nekohasekai.sagernet.fmt.TAG_PROXY
|
||||||
import io.nekohasekai.sagernet.ktx.Logs
|
import io.nekohasekai.sagernet.ktx.Logs
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlin.time.DurationUnit
|
import kotlin.time.DurationUnit
|
||||||
@ -55,6 +56,8 @@ class TrafficLooper
|
|||||||
|
|
||||||
var trafficUpdater: TrafficUpdater? = null
|
var trafficUpdater: TrafficUpdater? = null
|
||||||
var proxy: ProxyInstance?
|
var proxy: ProxyInstance?
|
||||||
|
|
||||||
|
// for display
|
||||||
var itemMain: TrafficUpdater.TrafficLooperData? = null
|
var itemMain: TrafficUpdater.TrafficLooperData? = null
|
||||||
var itemMainBase: TrafficUpdater.TrafficLooperData? = null
|
var itemMainBase: TrafficUpdater.TrafficLooperData? = null
|
||||||
var itemBypass: TrafficUpdater.TrafficLooperData? = null
|
var itemBypass: TrafficUpdater.TrafficLooperData? = null
|
||||||
@ -77,7 +80,7 @@ class TrafficLooper
|
|||||||
rx = ent.rx,
|
rx = ent.rx,
|
||||||
tx = ent.tx,
|
tx = ent.tx,
|
||||||
)
|
)
|
||||||
if (ent.id == proxy.config.mainEntId) {
|
if (proxy.config.selectorGroupId < 0L && ent.id == proxy.config.mainEntId) {
|
||||||
itemMain = item
|
itemMain = item
|
||||||
itemMainBase = TrafficUpdater.TrafficLooperData(
|
itemMainBase = TrafficUpdater.TrafficLooperData(
|
||||||
tag = tag,
|
tag = tag,
|
||||||
@ -91,6 +94,10 @@ class TrafficLooper
|
|||||||
Logs.d("traffic count $tag to ${ent.id}")
|
Logs.d("traffic count $tag to ${ent.id}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (proxy.config.selectorGroupId >= 0L) {
|
||||||
|
itemMain = TrafficUpdater.TrafficLooperData(tag = TAG_PROXY)
|
||||||
|
itemMainBase = TrafficUpdater.TrafficLooperData(tag = TAG_PROXY)
|
||||||
|
}
|
||||||
//
|
//
|
||||||
trafficUpdater = TrafficUpdater(
|
trafficUpdater = TrafficUpdater(
|
||||||
box = proxy.box, items = items.values.toList()
|
box = proxy.box, items = items.values.toList()
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import io.nekohasekai.sagernet.Key
|
|||||||
import io.nekohasekai.sagernet.bg.VpnService
|
import io.nekohasekai.sagernet.bg.VpnService
|
||||||
import io.nekohasekai.sagernet.database.DataStore
|
import io.nekohasekai.sagernet.database.DataStore
|
||||||
import io.nekohasekai.sagernet.database.ProxyEntity
|
import io.nekohasekai.sagernet.database.ProxyEntity
|
||||||
|
import io.nekohasekai.sagernet.database.ProxyEntity.Companion.TYPE_CHAIN
|
||||||
import io.nekohasekai.sagernet.database.ProxyEntity.Companion.TYPE_CONFIG
|
import io.nekohasekai.sagernet.database.ProxyEntity.Companion.TYPE_CONFIG
|
||||||
import io.nekohasekai.sagernet.database.SagerDatabase
|
import io.nekohasekai.sagernet.database.SagerDatabase
|
||||||
import io.nekohasekai.sagernet.fmt.ConfigBuildResult.IndexEntity
|
import io.nekohasekai.sagernet.fmt.ConfigBuildResult.IndexEntity
|
||||||
@ -53,6 +54,7 @@ class ConfigBuildResult(
|
|||||||
var externalIndex: List<IndexEntity>,
|
var externalIndex: List<IndexEntity>,
|
||||||
var mainEntId: Long,
|
var mainEntId: Long,
|
||||||
var trafficMap: Map<String, List<ProxyEntity>>,
|
var trafficMap: Map<String, List<ProxyEntity>>,
|
||||||
|
var profileTagMap: Map<Long, String>,
|
||||||
val alerts: List<Pair<Int, String>>,
|
val alerts: List<Pair<Int, String>>,
|
||||||
val selectorGroupId: Long,
|
val selectorGroupId: Long,
|
||||||
) {
|
) {
|
||||||
@ -85,6 +87,7 @@ fun buildConfig(
|
|||||||
listOf(),
|
listOf(),
|
||||||
proxy.id, //
|
proxy.id, //
|
||||||
mapOf(TAG_PROXY to listOf(proxy)), //
|
mapOf(TAG_PROXY to listOf(proxy)), //
|
||||||
|
mapOf(proxy.id to TAG_PROXY), //
|
||||||
listOf(),
|
listOf(),
|
||||||
-1L
|
-1L
|
||||||
)
|
)
|
||||||
@ -92,6 +95,7 @@ fun buildConfig(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val trafficMap = HashMap<String, MutableList<ProxyEntity>>()
|
val trafficMap = HashMap<String, MutableList<ProxyEntity>>()
|
||||||
|
val tagMap = HashMap<Long, String>()
|
||||||
val globalOutbounds = ArrayList<Long>()
|
val globalOutbounds = ArrayList<Long>()
|
||||||
val group = SagerDatabase.groupDao.getById(proxy.groupId)
|
val group = SagerDatabase.groupDao.getById(proxy.groupId)
|
||||||
var optionsToMerge = ""
|
var optionsToMerge = ""
|
||||||
@ -126,9 +130,9 @@ fun buildConfig(
|
|||||||
|
|
||||||
val extraRules = if (forTest) listOf() else SagerDatabase.rulesDao.enabledRules()
|
val extraRules = if (forTest) listOf() else SagerDatabase.rulesDao.enabledRules()
|
||||||
val extraProxies =
|
val extraProxies =
|
||||||
(if (forTest) mapOf() else SagerDatabase.proxyDao.getEntities(extraRules.mapNotNull { rule ->
|
if (forTest) mapOf() else SagerDatabase.proxyDao.getEntities(extraRules.mapNotNull { rule ->
|
||||||
rule.outbound.takeIf { it > 0 && it != proxy.id }
|
rule.outbound.takeIf { it > 0 && it != proxy.id }
|
||||||
}.toHashSet().toList()).associate { it.id to it.resolveChain() }).toMutableMap()
|
}.toHashSet().toList()).associate { it.id to it }
|
||||||
val buildSelector = !forTest && group?.isSelector == true
|
val buildSelector = !forTest && group?.isSelector == true
|
||||||
val uidListDNSRemote = mutableListOf<Int>()
|
val uidListDNSRemote = mutableListOf<Int>()
|
||||||
val uidListDNSDirect = mutableListOf<Int>()
|
val uidListDNSDirect = mutableListOf<Int>()
|
||||||
@ -261,8 +265,9 @@ fun buildConfig(
|
|||||||
|
|
||||||
// returns outbound tag
|
// returns outbound tag
|
||||||
fun buildChain(
|
fun buildChain(
|
||||||
chainId: Long, profileList: List<ProxyEntity>
|
chainId: Long, entity: ProxyEntity
|
||||||
): String {
|
): String {
|
||||||
|
val profileList = entity.resolveChain()
|
||||||
var currentOutbound = mutableMapOf<String, Any>()
|
var currentOutbound = mutableMapOf<String, Any>()
|
||||||
lateinit var pastOutbound: MutableMap<String, Any>
|
lateinit var pastOutbound: MutableMap<String, Any>
|
||||||
lateinit var pastInboundTag: String
|
lateinit var pastInboundTag: String
|
||||||
@ -337,7 +342,7 @@ fun buildConfig(
|
|||||||
|
|
||||||
// include g-xx & chain ent
|
// include g-xx & chain ent
|
||||||
val mapList = mutableListOf(proxyEntity)
|
val mapList = mutableListOf(proxyEntity)
|
||||||
if (index == 0 && profileList.size > 1) mapList.add(proxy) // chain ent
|
if (index == 0 && entity.type == TYPE_CHAIN) mapList.add(proxy) // chain ent
|
||||||
trafficMap[tagOut] = mapList
|
trafficMap[tagOut] = mapList
|
||||||
|
|
||||||
// Chain outbound
|
// Chain outbound
|
||||||
@ -460,11 +465,10 @@ fun buildConfig(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// build outbounds
|
// build outbounds
|
||||||
val tagMap = mutableMapOf<Long, String>()
|
|
||||||
if (buildSelector) {
|
if (buildSelector) {
|
||||||
val list = group?.id?.let { SagerDatabase.proxyDao.getByGroup(it) }
|
val list = group?.id?.let { SagerDatabase.proxyDao.getByGroup(it) }
|
||||||
list?.forEach {
|
list?.forEach {
|
||||||
tagMap[it.id] = buildChain(it.id, it.resolveChain())
|
tagMap[it.id] = buildChain(it.id, it)
|
||||||
}
|
}
|
||||||
outbounds.add(0, Outbound_SelectorOptions().apply {
|
outbounds.add(0, Outbound_SelectorOptions().apply {
|
||||||
type = "selector"
|
type = "selector"
|
||||||
@ -473,11 +477,11 @@ fun buildConfig(
|
|||||||
outbounds = tagMap.values.toList()
|
outbounds = tagMap.values.toList()
|
||||||
}.asMap())
|
}.asMap())
|
||||||
} else {
|
} else {
|
||||||
buildChain(0, proxy.resolveChain())
|
buildChain(0, proxy)
|
||||||
}
|
}
|
||||||
// build outbounds from route item
|
// build outbounds from route item
|
||||||
extraProxies.forEach { (key, entities) ->
|
extraProxies.forEach { (key, p) ->
|
||||||
tagMap[key] = buildChain(key, entities)
|
tagMap[key] = buildChain(key, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply user rules
|
// apply user rules
|
||||||
@ -756,6 +760,7 @@ fun buildConfig(
|
|||||||
externalIndexMap,
|
externalIndexMap,
|
||||||
proxy.id,
|
proxy.id,
|
||||||
trafficMap,
|
trafficMap,
|
||||||
|
tagMap,
|
||||||
alerts,
|
alerts,
|
||||||
if (buildSelector) group!!.id else -1L
|
if (buildSelector) group!!.id else -1L
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,14 +1,19 @@
|
|||||||
package io.nekohasekai.sagernet.ui
|
package io.nekohasekai.sagernet.ui
|
||||||
|
|
||||||
|
import android.Manifest.permission.POST_NOTIFICATIONS
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.RemoteException
|
import android.os.RemoteException
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.annotation.IdRes
|
import androidx.annotation.IdRes
|
||||||
|
import androidx.core.app.ActivityCompat
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.preference.PreferenceDataStore
|
import androidx.preference.PreferenceDataStore
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
@ -82,6 +87,17 @@ class MainActivity : ThemedActivity(),
|
|||||||
onNewIntent(intent)
|
onNewIntent(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sdk 33 notification
|
||||||
|
if (Build.VERSION.SDK_INT >= 33) {
|
||||||
|
val checkPermission =
|
||||||
|
ContextCompat.checkSelfPermission(this@MainActivity, POST_NOTIFICATIONS)
|
||||||
|
if (checkPermission != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
//动态申请
|
||||||
|
ActivityCompat.requestPermissions(
|
||||||
|
this@MainActivity, arrayOf<String>(POST_NOTIFICATIONS), 0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNewIntent(intent: Intent) {
|
override fun onNewIntent(intent: Intent) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user