From 4906ce8af58a87ea4b3536aa9cf7a6bf68c55d56 Mon Sep 17 00:00:00 2001 From: Mygod Date: Sun, 8 Nov 2015 18:43:07 +0800 Subject: [PATCH] Support switching to NAT/VPN without restarting the app --- .../com/github/shadowsocks/AppManager.scala | 8 ++-- .../com/github/shadowsocks/Shadowsocks.scala | 38 ++++++++----------- .../ShadowsocksRunnerActivity.scala | 17 +++------ .../ShadowsocksRunnerService.scala | 14 ++----- .../shadowsocks/database/ProfileManager.scala | 2 +- .../github/shadowsocks/utils/Constants.scala | 1 - .../com/github/shadowsocks/utils/Utils.scala | 9 +---- 7 files changed, 31 insertions(+), 58 deletions(-) diff --git a/src/main/scala/com/github/shadowsocks/AppManager.scala b/src/main/scala/com/github/shadowsocks/AppManager.scala index f75a9c94..88004783 100644 --- a/src/main/scala/com/github/shadowsocks/AppManager.scala +++ b/src/main/scala/com/github/shadowsocks/AppManager.scala @@ -247,8 +247,8 @@ class AppManager extends Activity with OnCheckedChangeListener with OnClickListe val array = proxiedAppString.split(" ") val bypass = array(0).toBoolean val apps = if (array.size > 1) array(1) else "" - prefs.edit.putBoolean(Key.isBypassApps, bypass).commit() - prefs.edit.putString(Key.proxied, apps).commit() + prefs.edit.putBoolean(Key.isBypassApps, bypass).apply() + prefs.edit.putString(Key.proxied, apps).apply() Toast.makeText(this, R.string.action_import_msg, Toast.LENGTH_SHORT).show() // Restart activity val intent = getIntent @@ -299,7 +299,7 @@ class AppManager extends Activity with OnCheckedChangeListener with OnClickListe val bypassSwitch = findViewById(R.id.bypassSwitch).asInstanceOf[Switch] val prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext) bypassSwitch.setOnCheckedChangeListener((button: CompoundButton, checked: Boolean) => - prefs.edit().putBoolean(Key.isBypassApps, checked).commit()) + prefs.edit().putBoolean(Key.isBypassApps, checked).apply()) bypassSwitch.setChecked(prefs.getBoolean(Key.isBypassApps, false)) appListView = findViewById(R.id.applistview).asInstanceOf[ListView] @@ -325,7 +325,7 @@ class AppManager extends Activity with OnCheckedChangeListener with OnClickListe }) val edit: SharedPreferences.Editor = prefs.edit edit.putString(Key.proxied, proxiedApps.toString()) - edit.commit + edit.apply } val loadStartRunnable = new Runnable { diff --git a/src/main/scala/com/github/shadowsocks/Shadowsocks.scala b/src/main/scala/com/github/shadowsocks/Shadowsocks.scala index fd6ece5b..82f77202 100644 --- a/src/main/scala/com/github/shadowsocks/Shadowsocks.scala +++ b/src/main/scala/com/github/shadowsocks/Shadowsocks.scala @@ -223,7 +223,7 @@ class Shadowsocks state = bgService.getState if (!status.getBoolean(getVersionName, false)) { - status.edit.putBoolean(getVersionName, true).commit() + status.edit.putBoolean(getVersionName, true).apply() recovery() } } @@ -515,13 +515,13 @@ class Shadowsocks title.setOnLongClickListener((v: View) => { if (Utils.isLollipopOrAbove && bgService != null && (bgService.getState == State.INIT || bgService.getState == State.STOPPED)) { - val natEnabled = status.getBoolean(Key.isNAT, false) - status.edit().putBoolean(Key.isNAT, !natEnabled).commit() - if (!natEnabled) { - Toast.makeText(getBaseContext, R.string.enable_nat, Toast.LENGTH_LONG).show() - } else { - Toast.makeText(getBaseContext, R.string.disable_nat, Toast.LENGTH_LONG).show() - } + val natEnabled = !status.getBoolean(Key.isNAT, !Utils.isLollipopOrAbove) + status.edit().putBoolean(Key.isNAT, natEnabled).apply() + deattachService() + attachService() + if (!Utils.isLollipopOrAbove) setPreferenceEnabled(State.isAvailable(bgService.getState)) + Toast.makeText(getBaseContext, if (natEnabled) R.string.enable_nat else R.string.disable_nat, Toast.LENGTH_LONG) + .show() true } else { false @@ -532,13 +532,9 @@ class Shadowsocks registerReceiver(preferenceReceiver, new IntentFilter(Action.UPDATE_PREFS)) // Bind to the service - Future { - val isRoot = (!Utils.isLollipopOrAbove || status.getBoolean(Key.isNAT, false)) && Console.isRoot - handler.post(() => { - status.edit.putBoolean(Key.isRoot, isRoot).commit() - attachService() - }) - } + handler.post(() => { + attachService() + }) } def attachService() { @@ -942,15 +938,10 @@ class Shadowsocks } } + var isRoot: Option[Boolean] = None def isVpnEnabled: Boolean = { - if (vpnEnabled < 0) { - vpnEnabled = if (!status.getBoolean(Key.isRoot, false)) { - 1 - } else { - 0 - } - } - if (vpnEnabled == 1) true else false + if (isRoot.isEmpty) isRoot = Some(Console.isRoot) + !(isRoot.get && status.getBoolean(Key.isNAT, !Utils.isLollipopOrAbove)) } def serviceStop() { @@ -1051,6 +1042,7 @@ class Shadowsocks fab.setImageResource(R.drawable.ic_cloud_queue) fab.setEnabled(false) fabProgressCircle.show() + setPreferenceEnabled(enabled = false) } state = s }) diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksRunnerActivity.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksRunnerActivity.scala index 133c0add..7b2d3817 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksRunnerActivity.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksRunnerActivity.scala @@ -65,19 +65,13 @@ class ShadowsocksRunnerActivity extends Activity { } // Variables - var vpnEnabled = -1 - var bgService: IShadowsocksService = null - var receiver:BroadcastReceiver = null + var isRoot: Option[Boolean] = None + var bgService: IShadowsocksService = _ + var receiver:BroadcastReceiver = _ def isVpnEnabled: Boolean = { - if (vpnEnabled < 0) { - vpnEnabled = if ((!Utils.isLollipopOrAbove || status.getBoolean(Key.isNAT, false)) && Console.isRoot) { - 0 - } else { - 1 - } - } - if (vpnEnabled == 1) true else false + if (isRoot.isEmpty) isRoot = Some(Console.isRoot) + !(isRoot.get && status.getBoolean(Key.isNAT, !Utils.isLollipopOrAbove)) } @@ -127,6 +121,7 @@ class ShadowsocksRunnerActivity extends Activity { } else { attachService() } + finish } override def onDestroy() { diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksRunnerService.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksRunnerService.scala index 981c5d30..e27168f2 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksRunnerService.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksRunnerService.scala @@ -64,18 +64,12 @@ class ShadowsocksRunnerService extends Service { } // Variables - var vpnEnabled = -1 - var bgService: IShadowsocksService = null + var isRoot: Option[Boolean] = None + var bgService: IShadowsocksService = _ def isVpnEnabled: Boolean = { - if (vpnEnabled < 0) { - vpnEnabled = if ((!Utils.isLollipopOrAbove || status.getBoolean(Key.isNAT, false)) && Console.isRoot) { - 0 - } else { - 1 - } - } - if (vpnEnabled == 1) true else false + if (isRoot.isEmpty) isRoot = Some(Console.isRoot) + !(isRoot.get && status.getBoolean(Key.isNAT, !Utils.isLollipopOrAbove)) } override def onBind(intent: Intent): IBinder = { diff --git a/src/main/scala/com/github/shadowsocks/database/ProfileManager.scala b/src/main/scala/com/github/shadowsocks/database/ProfileManager.scala index 149dead4..08ea17d3 100644 --- a/src/main/scala/com/github/shadowsocks/database/ProfileManager.scala +++ b/src/main/scala/com/github/shadowsocks/database/ProfileManager.scala @@ -133,7 +133,7 @@ class ProfileManager(settings: SharedPreferences, dbHelper: DBHelper) { edit.putString(Key.proxied, profile.individual) edit.putInt(Key.profileId, profile.id) edit.putString(Key.route, profile.route) - edit.commit() + edit.apply() profile } diff --git a/src/main/scala/com/github/shadowsocks/utils/Constants.scala b/src/main/scala/com/github/shadowsocks/utils/Constants.scala index 83ab3cfb..3d812e9b 100644 --- a/src/main/scala/com/github/shadowsocks/utils/Constants.scala +++ b/src/main/scala/com/github/shadowsocks/utils/Constants.scala @@ -66,7 +66,6 @@ object Key { val proxied = "Proxyed" val isNAT = "isNAT" - val isRoot = "isRoot" val status = "status" val proxyedApps = "proxyedApps" val route = "route" diff --git a/src/main/scala/com/github/shadowsocks/utils/Utils.scala b/src/main/scala/com/github/shadowsocks/utils/Utils.scala index f9f7fc2b..85b14a47 100644 --- a/src/main/scala/com/github/shadowsocks/utils/Utils.scala +++ b/src/main/scala/com/github/shadowsocks/utils/Utils.scala @@ -75,20 +75,13 @@ object Utils { val TIME_OUT: Int = -99 var initialized: Boolean = false var hasRedirectSupport: Int = -1 - var isRoot: Int = -1 var shell: String = null var root_shell: String = null var iptables: String = null var data_path: String = null var rootTries = 0 - def isLollipopOrAbove: Boolean = { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - true - } else { - false - } - } + def isLollipopOrAbove: Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP def getSignature(context: Context): String = { val info = context