mirror of
https://github.com/MatsuriDayo/NekoBoxForAndroid.git
synced 2025-12-20 07:00:05 +08:00
improve selector
This commit is contained in:
parent
6559e70b82
commit
c3aafbfdc9
@ -280,10 +280,12 @@ class SagerNet : Application(),
|
|||||||
.filterValues { it == tag }.keys.firstOrNull() ?: -1
|
.filterValues { it == tag }.keys.firstOrNull() ?: -1
|
||||||
val ent = SagerDatabase.proxyDao.getById(id) ?: return@runOnDefaultDispatcher
|
val ent = SagerDatabase.proxyDao.getById(id) ?: return@runOnDefaultDispatcher
|
||||||
// traffic & title
|
// traffic & title
|
||||||
data.proxy!!.looper?.selectMain(id)
|
data.proxy?.apply {
|
||||||
val title = ServiceNotification.genTitle(ent)
|
looper?.selectMain(id)
|
||||||
data.notification?.postNotificationTitle(title)
|
displayProfileName = ServiceNotification.genTitle(ent)
|
||||||
// post MainActivity animation
|
data.notification?.postNotificationTitle(displayProfileName)
|
||||||
|
}
|
||||||
|
// post binder
|
||||||
data.binder.broadcast { b ->
|
data.binder.broadcast { b ->
|
||||||
b.cbSelectorUpdate(id)
|
b.cbSelectorUpdate(id)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -88,7 +88,7 @@ class BaseService {
|
|||||||
override val coroutineContext = Dispatchers.Main.immediate + Job()
|
override val coroutineContext = Dispatchers.Main.immediate + Job()
|
||||||
|
|
||||||
override fun getState(): Int = (data?.state ?: State.Idle).ordinal
|
override fun getState(): Int = (data?.state ?: State.Idle).ordinal
|
||||||
override fun getProfileName(): String = data?.proxy?.profile?.displayName() ?: "Idle"
|
override fun getProfileName(): String = data?.proxy?.displayProfileName ?: "Idle"
|
||||||
|
|
||||||
override fun registerCallback(cb: ISagerNetServiceCallback, id: Int) {
|
override fun registerCallback(cb: ISagerNetServiceCallback, id: Int) {
|
||||||
if (!callbackIdMap.contains(cb)) {
|
if (!callbackIdMap.contains(cb)) {
|
||||||
@ -189,7 +189,6 @@ class BaseService {
|
|||||||
tmpBox.buildConfigTmp()
|
tmpBox.buildConfigTmp()
|
||||||
if (tmpBox.lastSelectorGroupId == data.proxy?.lastSelectorGroupId) {
|
if (tmpBox.lastSelectorGroupId == data.proxy?.lastSelectorGroupId) {
|
||||||
return true
|
return true
|
||||||
// TODO if profile changed?
|
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,23 +1,3 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* *
|
|
||||||
* Copyright (C) 2017 by Max Lv <max.c.lv@gmail.com> *
|
|
||||||
* Copyright (C) 2017 by Mygod Studio <contact-shadowsocks-android@mygod.be> *
|
|
||||||
* *
|
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
|
||||||
* it under the terms of the GNU General Public License as published by *
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
* This program is distributed in the hope that it will be useful, *
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
||||||
* GNU General Public License for more details. *
|
|
||||||
* *
|
|
||||||
* You should have received a copy of the GNU General Public License *
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
|
||||||
* *
|
|
||||||
*******************************************************************************/
|
|
||||||
|
|
||||||
package io.nekohasekai.sagernet.bg
|
package io.nekohasekai.sagernet.bg
|
||||||
|
|
||||||
import android.graphics.drawable.Icon
|
import android.graphics.drawable.Icon
|
||||||
@ -26,6 +6,7 @@ import androidx.annotation.RequiresApi
|
|||||||
import io.nekohasekai.sagernet.R
|
import io.nekohasekai.sagernet.R
|
||||||
import io.nekohasekai.sagernet.SagerNet
|
import io.nekohasekai.sagernet.SagerNet
|
||||||
import io.nekohasekai.sagernet.aidl.ISagerNetService
|
import io.nekohasekai.sagernet.aidl.ISagerNetService
|
||||||
|
import io.nekohasekai.sagernet.database.SagerDatabase
|
||||||
import android.service.quicksettings.TileService as BaseTileService
|
import android.service.quicksettings.TileService as BaseTileService
|
||||||
|
|
||||||
@RequiresApi(24)
|
@RequiresApi(24)
|
||||||
@ -39,16 +20,21 @@ class TileService : BaseTileService(), SagerConnection.Callback {
|
|||||||
|
|
||||||
private val connection = SagerConnection(SagerConnection.CONNECTION_ID_TILE)
|
private val connection = SagerConnection(SagerConnection.CONNECTION_ID_TILE)
|
||||||
override fun stateChanged(state: BaseService.State, profileName: String?, msg: String?) =
|
override fun stateChanged(state: BaseService.State, profileName: String?, msg: String?) =
|
||||||
updateTile(state) { profileName }
|
updateTile(state, profileName)
|
||||||
|
|
||||||
override fun onServiceConnected(service: ISagerNetService) {
|
override fun onServiceConnected(service: ISagerNetService) {
|
||||||
updateTile(BaseService.State.values()[service.state]) { service.profileName }
|
updateTile(BaseService.State.values()[service.state], service.profileName)
|
||||||
if (tapPending) {
|
if (tapPending) {
|
||||||
tapPending = false
|
tapPending = false
|
||||||
onClick()
|
onClick()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun cbSelectorUpdate(id: Long) {
|
||||||
|
val profile = SagerDatabase.proxyDao.getById(id) ?: return
|
||||||
|
updateTile(BaseService.State.Connected, profile.displayName())
|
||||||
|
}
|
||||||
|
|
||||||
override fun onStartListening() {
|
override fun onStartListening() {
|
||||||
super.onStartListening()
|
super.onStartListening()
|
||||||
connection.connect(this, this)
|
connection.connect(this, this)
|
||||||
@ -63,7 +49,7 @@ class TileService : BaseTileService(), SagerConnection.Callback {
|
|||||||
if (isLocked) unlockAndRun(this::toggle) else toggle()
|
if (isLocked) unlockAndRun(this::toggle) else toggle()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateTile(serviceState: BaseService.State, profileName: () -> String?) {
|
private fun updateTile(serviceState: BaseService.State, profileName: String?) {
|
||||||
qsTile?.apply {
|
qsTile?.apply {
|
||||||
label = null
|
label = null
|
||||||
when (serviceState) {
|
when (serviceState) {
|
||||||
@ -75,7 +61,7 @@ class TileService : BaseTileService(), SagerConnection.Callback {
|
|||||||
|
|
||||||
BaseService.State.Connected -> {
|
BaseService.State.Connected -> {
|
||||||
icon = iconConnected
|
icon = iconConnected
|
||||||
label = profileName()
|
label = profileName
|
||||||
state = Tile.STATE_ACTIVE
|
state = Tile.STATE_ACTIVE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -95,9 +95,8 @@ class VpnService : BaseVpnService(),
|
|||||||
// val tunOptions = JSONObject(tunOptionsJson)
|
// val tunOptions = JSONObject(tunOptionsJson)
|
||||||
|
|
||||||
// address & route & MTU ...... use NB4A GUI config
|
// address & route & MTU ...... use NB4A GUI config
|
||||||
val profile = data.proxy!!.profile
|
|
||||||
val builder = Builder().setConfigureIntent(SagerNet.configureIntent(this))
|
val builder = Builder().setConfigureIntent(SagerNet.configureIntent(this))
|
||||||
.setSession(profile.displayName())
|
.setSession(getString(R.string.app_name))
|
||||||
.setMtu(DataStore.mtu)
|
.setMtu(DataStore.mtu)
|
||||||
val ipv6Mode = DataStore.ipv6Mode
|
val ipv6Mode = DataStore.ipv6Mode
|
||||||
|
|
||||||
@ -132,10 +131,10 @@ class VpnService : BaseVpnService(),
|
|||||||
|
|
||||||
// app route
|
// app route
|
||||||
val packageName = packageName
|
val packageName = packageName
|
||||||
var proxyApps = DataStore.proxyApps
|
val proxyApps = DataStore.proxyApps
|
||||||
var bypass = DataStore.bypass
|
var bypass = DataStore.bypass
|
||||||
var workaroundSYSTEM = false /* DataStore.tunImplementation == TunImplementation.SYSTEM */
|
val workaroundSYSTEM = false /* DataStore.tunImplementation == TunImplementation.SYSTEM */
|
||||||
var needBypassRootUid = workaroundSYSTEM || data.proxy!!.config.trafficMap.values.any {
|
val needBypassRootUid = workaroundSYSTEM || data.proxy!!.config.trafficMap.values.any {
|
||||||
it[0].nekoBean?.needBypassRootUid() == true || it[0].hysteriaBean?.protocol == HysteriaBean.PROTOCOL_FAKETCP
|
it[0].nekoBean?.needBypassRootUid() == true || it[0].hysteriaBean?.protocol == HysteriaBean.PROTOCOL_FAKETCP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -67,10 +67,12 @@ abstract class BoxInstance(
|
|||||||
initPlugin("trojan-go-plugin")
|
initPlugin("trojan-go-plugin")
|
||||||
pluginConfigs[port] = profile.type to bean.buildTrojanGoConfig(port)
|
pluginConfigs[port] = profile.type to bean.buildTrojanGoConfig(port)
|
||||||
}
|
}
|
||||||
|
|
||||||
is NaiveBean -> {
|
is NaiveBean -> {
|
||||||
initPlugin("naive-plugin")
|
initPlugin("naive-plugin")
|
||||||
pluginConfigs[port] = profile.type to bean.buildNaiveConfig(port)
|
pluginConfigs[port] = profile.type to bean.buildNaiveConfig(port)
|
||||||
}
|
}
|
||||||
|
|
||||||
is HysteriaBean -> {
|
is HysteriaBean -> {
|
||||||
initPlugin("hysteria-plugin")
|
initPlugin("hysteria-plugin")
|
||||||
pluginConfigs[port] = profile.type to bean.buildHysteriaConfig(port) {
|
pluginConfigs[port] = profile.type to bean.buildHysteriaConfig(port) {
|
||||||
@ -82,6 +84,7 @@ abstract class BoxInstance(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is TuicBean -> {
|
is TuicBean -> {
|
||||||
initPlugin("tuic-plugin")
|
initPlugin("tuic-plugin")
|
||||||
pluginConfigs[port] = profile.type to bean.buildTuicConfig(port) {
|
pluginConfigs[port] = profile.type to bean.buildTuicConfig(port) {
|
||||||
@ -94,6 +97,7 @@ abstract class BoxInstance(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is NekoBean -> {
|
is NekoBean -> {
|
||||||
// check if plugin binary can be loaded
|
// check if plugin binary can be loaded
|
||||||
initPlugin(bean.plgId)
|
initPlugin(bean.plgId)
|
||||||
@ -127,6 +131,7 @@ abstract class BoxInstance(
|
|||||||
externalInstances.containsKey(port) -> {
|
externalInstances.containsKey(port) -> {
|
||||||
externalInstances[port]!!.launch()
|
externalInstances[port]!!.launch()
|
||||||
}
|
}
|
||||||
|
|
||||||
bean is TrojanGoBean -> {
|
bean is TrojanGoBean -> {
|
||||||
val configFile = File(
|
val configFile = File(
|
||||||
cache, "trojan_go_" + SystemClock.elapsedRealtime() + ".json"
|
cache, "trojan_go_" + SystemClock.elapsedRealtime() + ".json"
|
||||||
@ -141,6 +146,7 @@ abstract class BoxInstance(
|
|||||||
|
|
||||||
processes.start(commands)
|
processes.start(commands)
|
||||||
}
|
}
|
||||||
|
|
||||||
bean is NaiveBean -> {
|
bean is NaiveBean -> {
|
||||||
val configFile = File(
|
val configFile = File(
|
||||||
cache, "naive_" + SystemClock.elapsedRealtime() + ".json"
|
cache, "naive_" + SystemClock.elapsedRealtime() + ".json"
|
||||||
@ -170,6 +176,7 @@ abstract class BoxInstance(
|
|||||||
|
|
||||||
processes.start(commands, envMap)
|
processes.start(commands, envMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
bean is HysteriaBean -> {
|
bean is HysteriaBean -> {
|
||||||
val configFile = File(
|
val configFile = File(
|
||||||
cache, "hysteria_" + SystemClock.elapsedRealtime() + ".json"
|
cache, "hysteria_" + SystemClock.elapsedRealtime() + ".json"
|
||||||
@ -195,6 +202,7 @@ abstract class BoxInstance(
|
|||||||
|
|
||||||
processes.start(commands)
|
processes.start(commands)
|
||||||
}
|
}
|
||||||
|
|
||||||
bean is NekoBean -> {
|
bean is NekoBean -> {
|
||||||
// config built from JS
|
// config built from JS
|
||||||
val nekoRunConfigs = bean.allConfig.optJSONArray("nekoRunConfigs")
|
val nekoRunConfigs = bean.allConfig.optJSONArray("nekoRunConfigs")
|
||||||
@ -232,6 +240,7 @@ abstract class BoxInstance(
|
|||||||
|
|
||||||
processes.start(commands)
|
processes.start(commands)
|
||||||
}
|
}
|
||||||
|
|
||||||
bean is TuicBean -> {
|
bean is TuicBean -> {
|
||||||
val configFile = File(
|
val configFile = File(
|
||||||
context.noBackupFilesDir,
|
context.noBackupFilesDir,
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package io.nekohasekai.sagernet.bg.proto
|
|||||||
|
|
||||||
import io.nekohasekai.sagernet.BuildConfig
|
import io.nekohasekai.sagernet.BuildConfig
|
||||||
import io.nekohasekai.sagernet.bg.BaseService
|
import io.nekohasekai.sagernet.bg.BaseService
|
||||||
|
import io.nekohasekai.sagernet.bg.ServiceNotification
|
||||||
import io.nekohasekai.sagernet.database.ProxyEntity
|
import io.nekohasekai.sagernet.database.ProxyEntity
|
||||||
import io.nekohasekai.sagernet.ktx.Logs
|
import io.nekohasekai.sagernet.ktx.Logs
|
||||||
import io.nekohasekai.sagernet.ktx.runOnDefaultDispatcher
|
import io.nekohasekai.sagernet.ktx.runOnDefaultDispatcher
|
||||||
@ -11,9 +12,11 @@ import moe.matsuri.nb4a.utils.JavaUtil
|
|||||||
class ProxyInstance(profile: ProxyEntity, var service: BaseService.Interface? = null) :
|
class ProxyInstance(profile: ProxyEntity, var service: BaseService.Interface? = null) :
|
||||||
BoxInstance(profile) {
|
BoxInstance(profile) {
|
||||||
|
|
||||||
var lastSelectorGroupId = -1L
|
|
||||||
var notTmp = true
|
var notTmp = true
|
||||||
|
|
||||||
|
var lastSelectorGroupId = -1L
|
||||||
|
var displayProfileName = ServiceNotification.genTitle(profile)
|
||||||
|
|
||||||
// for TrafficLooper
|
// for TrafficLooper
|
||||||
var looper: TrafficLooper? = null
|
var looper: TrafficLooper? = null
|
||||||
|
|
||||||
|
|||||||
@ -61,6 +61,7 @@ class TrafficLooper
|
|||||||
tag = selectorNowFakeTag
|
tag = selectorNowFakeTag
|
||||||
ignore = true
|
ignore = true
|
||||||
// post traffic when switch
|
// post traffic when switch
|
||||||
|
if (DataStore.profileTrafficStatistics) {
|
||||||
data.proxy?.config?.trafficMap?.get(tag)?.firstOrNull()?.let {
|
data.proxy?.config?.trafficMap?.get(tag)?.firstOrNull()?.let {
|
||||||
it.rx = rx
|
it.rx = rx
|
||||||
it.tx = tx
|
it.tx = tx
|
||||||
@ -69,6 +70,7 @@ class TrafficLooper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
selectorNowFakeTag = newData.tag
|
selectorNowFakeTag = newData.tag
|
||||||
selectorNowId = id
|
selectorNowId = id
|
||||||
newData.apply {
|
newData.apply {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user