From 28ea9dd8071cd8fb9c3ba566812eae5945c16428 Mon Sep 17 00:00:00 2001 From: Mygod Date: Tue, 24 May 2016 11:37:33 +0800 Subject: [PATCH] Use app.* instead of ShadowsocksApplication.* Because typing ShadowsocksApplication is quite troublesome. --- .../com/github/shadowsocks/AppManager.scala | 25 ++++----- .../com/github/shadowsocks/BaseService.scala | 5 +- .../shadowsocks/ProfileManagerActivity.scala | 37 +++++++------- .../shadowsocks/ServiceBoundContext.scala | 3 +- .../com/github/shadowsocks/Shadowsocks.scala | 51 ++++++++++--------- .../shadowsocks/ShadowsocksApplication.scala | 26 +++++----- .../shadowsocks/ShadowsocksNatService.scala | 7 +-- .../shadowsocks/ShadowsocksNotification.scala | 3 +- .../ShadowsocksQuickSwitchActivity.scala | 11 ++-- .../ShadowsocksRunnerActivity.scala | 7 +-- .../ShadowsocksRunnerService.scala | 7 +-- .../shadowsocks/ShadowsocksSettings.scala | 15 +++--- .../shadowsocks/ShadowsocksVpnService.scala | 7 +-- .../github/shadowsocks/TaskerActivity.scala | 3 +- .../github/shadowsocks/TaskerReceiver.scala | 5 +- .../shadowsocks/database/ProfileManager.scala | 4 +- .../shadowsocks/utils/ConfigUtils.scala | 13 ++--- .../shadowsocks/utils/TaskerSettings.scala | 5 +- .../shadowsocks/utils/TrafficMonitor.scala | 5 +- .../com/github/shadowsocks/utils/Utils.scala | 6 +-- 20 files changed, 132 insertions(+), 113 deletions(-) diff --git a/src/main/scala/com/github/shadowsocks/AppManager.scala b/src/main/scala/com/github/shadowsocks/AppManager.scala index eb64d29d..a632529f 100644 --- a/src/main/scala/com/github/shadowsocks/AppManager.scala +++ b/src/main/scala/com/github/shadowsocks/AppManager.scala @@ -53,6 +53,7 @@ import android.support.v7.widget.{DefaultItemAnimator, LinearLayoutManager, Recy import android.view._ import android.widget._ import com.github.shadowsocks.utils.{Key, Utils} +import com.github.shadowsocks.ShadowsocksApplication.app import scala.collection.JavaConversions._ import scala.collection.mutable @@ -71,7 +72,7 @@ object AppManager { val filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED) filter.addAction(Intent.ACTION_PACKAGE_REMOVED) filter.addDataScheme("package") - ShadowsocksApplication.instance.registerReceiver((context: Context, intent: Intent) => + app.registerReceiver((context: Context, intent: Intent) => if (intent.getAction != Intent.ACTION_PACKAGE_REMOVED || !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { synchronized(cachedApps = null) @@ -96,13 +97,13 @@ class AppManager extends AppCompatActivity with OnMenuItemClickListener { private final class AppViewHolder(val view: View) extends RecyclerView.ViewHolder(view) with View.OnClickListener { private val icon = itemView.findViewById(R.id.itemicon).asInstanceOf[ImageView] private val check = itemView.findViewById(R.id.itemcheck).asInstanceOf[Switch] - private var app: ProxiedApp = _ + private var item: ProxiedApp = _ itemView.setOnClickListener(this) - private def proxied = proxiedApps.contains(app.packageName) + private def proxied = proxiedApps.contains(item.packageName) def bind(app: ProxiedApp) { - this.app = app + this.item = app icon.setImageDrawable(app.icon) check.setText(app.name) check.setChecked(proxied) @@ -110,14 +111,14 @@ class AppManager extends AppCompatActivity with OnMenuItemClickListener { def onClick(v: View) { if (proxied) { - proxiedApps.remove(app.packageName) + proxiedApps.remove(item.packageName) check.setChecked(false) } else { - proxiedApps.add(app.packageName) + proxiedApps.add(item.packageName) check.setChecked(true) } if (!appsLoading.get) - ShadowsocksApplication.settings.edit.putString(Key.proxied, proxiedApps.mkString("\n")).apply + app.editor.putString(Key.proxied, proxiedApps.mkString("\n")).apply } } @@ -133,7 +134,7 @@ class AppManager extends AppCompatActivity with OnMenuItemClickListener { new AppViewHolder(LayoutInflater.from(vg.getContext).inflate(R.layout.layout_apps_item, vg, false)) } - private val proxiedApps = ShadowsocksApplication.settings.getString(Key.proxied, "").split('\n').to[mutable.HashSet] + private val proxiedApps = app.settings.getString(Key.proxied, "").split('\n').to[mutable.HashSet] private var toolbar: Toolbar = _ private var appListView: RecyclerView = _ private var loadingView: View = _ @@ -208,17 +209,17 @@ class AppManager extends AppCompatActivity with OnMenuItemClickListener { toolbar.inflateMenu(R.menu.app_manager_menu) toolbar.setOnMenuItemClickListener(this) - ShadowsocksApplication.settings.edit().putBoolean(Key.isProxyApps, true).commit() + app.editor.putBoolean(Key.isProxyApps, true).apply findViewById(R.id.onSwitch).asInstanceOf[Switch] .setOnCheckedChangeListener((_, checked) => { - ShadowsocksApplication.settings.edit().putBoolean(Key.isProxyApps, checked).commit() + app.editor.putBoolean(Key.isProxyApps, checked).apply finish() }) val bypassSwitch = findViewById(R.id.bypassSwitch).asInstanceOf[Switch] bypassSwitch.setOnCheckedChangeListener((_, checked) => - ShadowsocksApplication.settings.edit().putBoolean(Key.isBypassApps, checked).apply()) - bypassSwitch.setChecked(ShadowsocksApplication.settings.getBoolean(Key.isBypassApps, false)) + app.editor.putBoolean(Key.isBypassApps, checked).apply()) + bypassSwitch.setChecked(app.settings.getBoolean(Key.isBypassApps, false)) loadingView = findViewById(R.id.loading) appListView = findViewById(R.id.applistview).asInstanceOf[RecyclerView] diff --git a/src/main/scala/com/github/shadowsocks/BaseService.scala b/src/main/scala/com/github/shadowsocks/BaseService.scala index 5464a04c..709d7a55 100644 --- a/src/main/scala/com/github/shadowsocks/BaseService.scala +++ b/src/main/scala/com/github/shadowsocks/BaseService.scala @@ -49,6 +49,7 @@ import android.util.Log import android.widget.Toast import com.github.shadowsocks.aidl.{Config, IShadowsocksService, IShadowsocksServiceCallback} import com.github.shadowsocks.utils._ +import com.github.shadowsocks.ShadowsocksApplication.app trait BaseService extends Service { @@ -162,11 +163,11 @@ trait BaseService extends Service { def updateTrafficTotal(tx: Long, rx: Long) { val config = this.config // avoid race conditions without locking if (config != null) { - ShadowsocksApplication.profileManager.getProfile(config.profileId) match { + app.profileManager.getProfile(config.profileId) match { case Some(profile) => profile.tx += tx profile.rx += rx - ShadowsocksApplication.profileManager.updateProfile(profile) + app.profileManager.updateProfile(profile) case None => // Ignore } } diff --git a/src/main/scala/com/github/shadowsocks/ProfileManagerActivity.scala b/src/main/scala/com/github/shadowsocks/ProfileManagerActivity.scala index 52401d76..430a9f1e 100644 --- a/src/main/scala/com/github/shadowsocks/ProfileManagerActivity.scala +++ b/src/main/scala/com/github/shadowsocks/ProfileManagerActivity.scala @@ -22,6 +22,7 @@ import com.github.shadowsocks.aidl.IShadowsocksServiceCallback import com.github.shadowsocks.database.Profile import com.github.shadowsocks.utils.{Key, Parser, TrafficMonitor, Utils} import com.github.shadowsocks.widget.UndoSnackbarManager +import com.github.shadowsocks.ShadowsocksApplication.app import com.google.zxing.integration.android.IntentIntegrator import net.glxn.qrgen.android.QRCode @@ -96,7 +97,7 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic def bind(item: Profile) { this.item = item updateText() - if (item.id == ShadowsocksApplication.profileId) { + if (item.id == app.profileId) { text.setChecked(true) selectedItem = this } else { @@ -106,7 +107,7 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic } def onClick(v: View) { - ShadowsocksApplication.switchProfile(item.id) + app.switchProfile(item.id) finish } @@ -122,7 +123,7 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic private class ProfilesAdapter extends RecyclerView.Adapter[ProfileViewHolder] { var profiles = new ArrayBuffer[Profile] - profiles ++= ShadowsocksApplication.profileManager.getAllProfiles.getOrElse(List.empty[Profile]) + profiles ++= app.profileManager.getAllProfiles.getOrElse(List.empty[Profile]) def getItemCount = profiles.length @@ -149,11 +150,11 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic next.userOrder = previousOrder previousOrder = order profiles(i) = next - ShadowsocksApplication.profileManager.updateProfile(next) + app.profileManager.updateProfile(next) } first.userOrder = previousOrder profiles(to) = first - ShadowsocksApplication.profileManager.updateProfile(first) + app.profileManager.updateProfile(first) notifyItemMoved(from, to) } @@ -166,8 +167,8 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic notifyItemInserted(index) } def commit(actions: Iterator[(Int, Profile)]) = for ((index, item) <- actions) { - ShadowsocksApplication.profileManager.delProfile(item.id) - if (item.id == ShadowsocksApplication.profileId) ShadowsocksApplication.profileId(-1) + app.profileManager.delProfile(item.id) + if (item.id == app.profileId) app.profileId(-1) } } @@ -203,14 +204,14 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic initFab() - ShadowsocksApplication.profileManager.setProfileAddedListener(profilesAdapter.add) + app.profileManager.setProfileAddedListener(profilesAdapter.add) val profilesList = findViewById(R.id.profilesList).asInstanceOf[RecyclerView] val layoutManager = new LinearLayoutManager(this) profilesList.setLayoutManager(layoutManager) profilesList.setItemAnimator(new DefaultItemAnimator) profilesList.setAdapter(profilesAdapter) layoutManager.scrollToPosition(profilesAdapter.profiles.zipWithIndex.collectFirst { - case (profile, i) if profile.id == ShadowsocksApplication.profileId => i + case (profile, i) if profile.id == app.profileId => i }.getOrElse(-1)) undoManager = new UndoSnackbarManager[Profile](profilesList, profilesAdapter.undo, profilesAdapter.commit) new ItemTouchHelper(new SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN, @@ -232,8 +233,8 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic if (selectedItem != null) selectedItem.updateText(txTotal, rxTotal) }) - if (ShadowsocksApplication.settings.getBoolean(Key.profileTip, true)) { - ShadowsocksApplication.settings.edit.putBoolean(Key.profileTip, false).commit + if (app.settings.getBoolean(Key.profileTip, true)) { + app.editor.putBoolean(Key.profileTip, false).commit new AlertDialog.Builder(this).setTitle(R.string.profile_manager_dialog) .setMessage(R.string.profile_manager_dialog_content).setPositiveButton(R.string.gotcha, null).create.show } @@ -270,8 +271,8 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic v.getId match { case R.id.fab_manual_add => menu.toggle(true) - ShadowsocksApplication.profileManager.reload(-1) - ShadowsocksApplication.switchProfile(ShadowsocksApplication.profileManager.save.id) + app.profileManager.reload(-1) + app.switchProfile(app.profileManager.save.id) finish case R.id.fab_qrcode_add => menu.toggle(false) @@ -301,7 +302,7 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic if (clipboard.hasPrimaryClip) { val profiles = Parser.findAll(clipboard.getPrimaryClip.getItemAt(0).getText) if (profiles.nonEmpty) { - profiles.foreach(ShadowsocksApplication.profileManager.createProfile) + profiles.foreach(app.profileManager.createProfile) Toast.makeText(this, R.string.action_import_msg, Toast.LENGTH_SHORT).show return } @@ -346,7 +347,7 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic val dialog = new AlertDialog.Builder(this) .setTitle(R.string.add_profile_dialog) .setPositiveButton(android.R.string.yes, ((_, _) => - profiles.foreach(ShadowsocksApplication.profileManager.createProfile)): DialogInterface.OnClickListener) + profiles.foreach(app.profileManager.createProfile)): DialogInterface.OnClickListener) .setNegativeButton(android.R.string.no, ((_, _) => finish()): DialogInterface.OnClickListener) .setMessage(profiles.mkString("\n")) .create() @@ -365,7 +366,7 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic override def onDestroy { detachService() undoManager.flush - ShadowsocksApplication.profileManager.setProfileAddedListener(null) + app.profileManager.setProfileAddedListener(null) super.onDestroy } @@ -374,7 +375,7 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic if (scanResult != null) { val contents = scanResult.getContents if (!TextUtils.isEmpty(contents)) - Parser.findAll(contents).foreach(ShadowsocksApplication.profileManager.createProfile) + Parser.findAll(contents).foreach(app.profileManager.createProfile) } } @@ -387,7 +388,7 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic def onMenuItemClick(item: MenuItem): Boolean = item.getItemId match { case R.id.action_export => - ShadowsocksApplication.profileManager.getAllProfiles match { + app.profileManager.getAllProfiles match { case Some(profiles) => clipboard.setPrimaryClip(ClipData.newPlainText(null, profiles.mkString("\n"))) Toast.makeText(this, R.string.action_export_msg, Toast.LENGTH_SHORT).show diff --git a/src/main/scala/com/github/shadowsocks/ServiceBoundContext.scala b/src/main/scala/com/github/shadowsocks/ServiceBoundContext.scala index d5b57400..8096ac65 100644 --- a/src/main/scala/com/github/shadowsocks/ServiceBoundContext.scala +++ b/src/main/scala/com/github/shadowsocks/ServiceBoundContext.scala @@ -4,6 +4,7 @@ import android.content.{ComponentName, Context, Intent, ServiceConnection} import android.os.{RemoteException, IBinder} import com.github.shadowsocks.aidl.{IShadowsocksServiceCallback, IShadowsocksService} import com.github.shadowsocks.utils.Action +import com.github.shadowsocks.ShadowsocksApplication.app /** * @author Mygod @@ -51,7 +52,7 @@ trait ServiceBoundContext extends Context { this.callback = callback if (bgService == null) { val s = - if (ShadowsocksApplication.isVpnEnabled) classOf[ShadowsocksVpnService] else classOf[ShadowsocksNatService] + if (app.isVpnEnabled) classOf[ShadowsocksVpnService] else classOf[ShadowsocksNatService] val intent = new Intent(this, s) intent.setAction(Action.SERVICE) diff --git a/src/main/scala/com/github/shadowsocks/Shadowsocks.scala b/src/main/scala/com/github/shadowsocks/Shadowsocks.scala index 18598513..bee76100 100644 --- a/src/main/scala/com/github/shadowsocks/Shadowsocks.scala +++ b/src/main/scala/com/github/shadowsocks/Shadowsocks.scala @@ -63,6 +63,7 @@ import com.github.shadowsocks.aidl.IShadowsocksServiceCallback import com.github.shadowsocks.database._ import com.github.shadowsocks.utils.CloseUtils._ import com.github.shadowsocks.utils._ +import com.github.shadowsocks.ShadowsocksApplication.app import com.google.android.gms.ads.{AdRequest, AdSize, AdView} import scala.collection.mutable.ArrayBuffer @@ -129,7 +130,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext { changeSwitch(checked = true) preferences.setEnabled(false) stat.setVisibility(View.VISIBLE) - if (ShadowsocksApplication.isVpnEnabled) { + if (app.isVpnEnabled) { connectionTestText.setVisibility(View.VISIBLE) connectionTestText.setText(getString(R.string.connection_test_pending)) } else connectionTestText.setVisibility(View.GONE) @@ -177,31 +178,31 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext { // Update the UI if (fab != null) fab.setEnabled(true) updateState() - if (Build.VERSION.SDK_INT >= 21 && !ShadowsocksApplication.isVpnEnabled) { + if (Build.VERSION.SDK_INT >= 21 && !app.isVpnEnabled) { val snackbar = Snackbar.make(findViewById(android.R.id.content), R.string.nat_deprecated, Snackbar.LENGTH_LONG) snackbar.setAction(R.string.switch_to_vpn, (_ => preferences.natSwitch.setChecked(false)): View.OnClickListener) snackbar.show } - if (!ShadowsocksApplication.settings.getBoolean(ShadowsocksApplication.getVersionName, false)) { - ShadowsocksApplication.settings.edit.putBoolean(ShadowsocksApplication.getVersionName, true).apply() + if (!app.settings.getBoolean(app.getVersionName, false)) { + app.editor.putBoolean(app.getVersionName, true).apply() try { // Workaround that convert port(String) to port(Int) - val oldLocalPort = ShadowsocksApplication.settings.getString(Key.localPort, "") - val oldRemotePort = ShadowsocksApplication.settings.getString(Key.remotePort, "") + val oldLocalPort = app.settings.getString(Key.localPort, "") + val oldRemotePort = app.settings.getString(Key.remotePort, "") if (oldLocalPort != "") { - ShadowsocksApplication.settings.edit.putInt(Key.localPort, oldLocalPort.toInt).apply() + app.editor.putInt(Key.localPort, oldLocalPort.toInt).apply() } if (oldRemotePort != "") { - ShadowsocksApplication.settings.edit.putInt(Key.remotePort, oldRemotePort.toInt).apply() + app.editor.putInt(Key.remotePort, oldRemotePort.toInt).apply() } } catch { case ex: Exception => // Ignore } - val oldProxiedApps = ShadowsocksApplication.settings.getString(Key.proxied, "") - if (oldProxiedApps.contains('|')) ShadowsocksApplication.settings.edit - .putString(Key.proxied, DBHelper.updateProxiedApps(this, oldProxiedApps)).apply() + val oldProxiedApps = app.settings.getString(Key.proxied, "") + if (oldProxiedApps.contains('|')) + app.editor.putString(Key.proxied, DBHelper.updateProxiedApps(this, oldProxiedApps)).apply() recovery() @@ -300,7 +301,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext { cmd.append("chmod 666 %s/%s-vpn.pid".formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir, task)) } - if (ShadowsocksApplication.isVpnEnabled) { + if (app.isVpnEnabled) { Console.runCommand(cmd.toArray) } else { Console.runRootCommand(cmd.toArray) @@ -324,7 +325,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext { cmd.append("rm -f %s/%s-vpn.pid".formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir, task)) cmd.append("rm -f %s/%s-vpn.conf".formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir, task)) } - if (ShadowsocksApplication.isVpnEnabled) Console.runCommand(cmd.toArray) else { + if (app.isVpnEnabled) Console.runCommand(cmd.toArray) else { Console.runRootCommand(cmd.toArray) Console.runRootCommand(Utils.iptables + " -t nat -F OUTPUT") } @@ -337,7 +338,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext { def prepareStartService() { Utils.ThrowableFuture { - if (ShadowsocksApplication.isVpnEnabled) { + if (app.isVpnEnabled) { val intent = VpnService.prepare(this) if (intent != null) { startActivityForResult(intent, REQUEST_CONNECT) @@ -406,7 +407,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext { result = getString(R.string.connection_test_error, e.getMessage) } synchronized(if (testCount == id) { - if (ShadowsocksApplication.isVpnEnabled) handler.post(() => { + if (app.isVpnEnabled) handler.post(() => { if (success) connectionTestText.setText(result) else { connectionTestText.setText(R.string.connection_test_fail) Snackbar.make(findViewById(android.R.id.content), result, Snackbar.LENGTH_LONG).show @@ -435,7 +436,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext { protected override def onPause() { super.onPause() - ShadowsocksApplication.profileManager.save + app.profileManager.save } private def hideCircle() { @@ -463,7 +464,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext { preferences.setEnabled(false) fabProgressCircle.postDelayed(hideCircle, 100) stat.setVisibility(View.VISIBLE) - if (ShadowsocksApplication.isVpnEnabled) { + if (app.isVpnEnabled) { connectionTestText.setVisibility(View.VISIBLE) connectionTestText.setText(getString(R.string.connection_test_pending)) } else connectionTestText.setVisibility(View.GONE) @@ -488,13 +489,13 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext { private def updateCurrentProfile() { // Check if current profile changed - if (ShadowsocksApplication.profileId != currentProfile.id) { - currentProfile = ShadowsocksApplication.currentProfile match { + if (app.profileId != currentProfile.id) { + currentProfile = app.currentProfile match { case Some(profile) => profile // updated case None => // removed - ShadowsocksApplication.profileManager.getFirstProfile match { - case Some(first) => ShadowsocksApplication.switchProfile(first.id) - case None => ShadowsocksApplication.profileManager.createDefault() + app.profileManager.getFirstProfile match { + case Some(first) => app.switchProfile(first.id) + case None => app.profileManager.createDefault() } } @@ -590,7 +591,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext { } def checkText(key: String): Boolean = { - val text = ShadowsocksApplication.settings.getString(key, "") + val text = app.settings.getString(key, "") if (text != null && text.length > 0) return true Snackbar.make(findViewById(android.R.id.content), R.string.proxy_empty, Snackbar.LENGTH_LONG).show false @@ -598,9 +599,9 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext { /** Called when connect button is clicked. */ def serviceLoad() { - bgService.use(ConfigUtils.load(ShadowsocksApplication.settings)) + bgService.use(ConfigUtils.load(app.settings)) - if (ShadowsocksApplication.isVpnEnabled) { + if (app.isVpnEnabled) { changeSwitch(checked = false) } } diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala index 2c0a7225..e1f10b07 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala @@ -45,26 +45,32 @@ import java.util.concurrent.TimeUnit import android.app.Application import android.content.pm.PackageManager import android.preference.PreferenceManager -import com.j256.ormlite.logger.LocalLog import com.github.shadowsocks.database.{DBHelper, ProfileManager} import com.github.shadowsocks.utils.{Key, Utils} import com.google.android.gms.analytics.{GoogleAnalytics, HitBuilders} import com.google.android.gms.common.api.ResultCallback import com.google.android.gms.tagmanager.{ContainerHolder, TagManager} +import com.j256.ormlite.logger.LocalLog object ShadowsocksApplication { - var instance: ShadowsocksApplication = _ - lazy val dbHelper = new DBHelper(instance) + var app: ShadowsocksApplication = _ +} + +class ShadowsocksApplication extends Application { + import ShadowsocksApplication._ + + lazy val dbHelper = new DBHelper(this) final val SIG_FUNC = "getSignature" var containerHolder: ContainerHolder = _ - lazy val tracker = GoogleAnalytics.getInstance(instance).newTracker(R.xml.tracker) - lazy val settings = PreferenceManager.getDefaultSharedPreferences(instance) + lazy val tracker = GoogleAnalytics.getInstance(this).newTracker(R.xml.tracker) + lazy val settings = PreferenceManager.getDefaultSharedPreferences(this) + lazy val editor = settings.edit lazy val profileManager = new ProfileManager(settings, dbHelper) def isVpnEnabled = !settings.getBoolean(Key.isNAT, false) def getVersionName = try { - instance.getPackageManager.getPackageInfo(instance.getPackageName, 0).versionName + getPackageManager.getPackageInfo(getPackageName, 0).versionName } catch { case _: PackageManager.NameNotFoundException => "Package name not found" case _: Throwable => null @@ -84,14 +90,10 @@ object ShadowsocksApplication { profileId(id) profileManager.load(id) } -} - -class ShadowsocksApplication extends Application { - import ShadowsocksApplication._ override def onCreate() { - java.lang.System.setProperty(LocalLog.LOCAL_LOG_LEVEL_PROPERTY, "ERROR"); - ShadowsocksApplication.instance = this + java.lang.System.setProperty(LocalLog.LOCAL_LOG_LEVEL_PROPERTY, "ERROR") + app = this val tm = TagManager.getInstance(this) val pending = tm.loadContainerPreferNonDefault("GTM-NT8WS8", R.raw.gtm_default_container) val callback = new ResultCallback[ContainerHolder] { diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala index 5e91267f..b3c1ce7c 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala @@ -50,6 +50,7 @@ import android.os._ import android.util.{Log, SparseArray} import com.github.shadowsocks.aidl.Config import com.github.shadowsocks.utils._ +import com.github.shadowsocks.ShadowsocksApplication.app import scala.collection.JavaConversions._ import scala.collection.mutable.ArrayBuffer @@ -355,13 +356,13 @@ class ShadowsocksNatService extends BaseService { } super.startRunner(config) - ShadowsocksApplication.track(TAG, "start") + app.track(TAG, "start") changeState(State.CONNECTING) Utils.ThrowableFuture { if (config.proxy == "198.199.101.152") { - val holder = ShadowsocksApplication.containerHolder + val holder = app.containerHolder try { this.config = ConfigUtils.getPublicConfig(getBaseContext, holder.getContainer, config) } catch { @@ -412,7 +413,7 @@ class ShadowsocksNatService extends BaseService { if (notification != null) notification.destroy() - ShadowsocksApplication.track(TAG, "stop") + app.track(TAG, "stop") // reset NAT killProcesses() diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksNotification.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksNotification.scala index 518eb32e..2dfe1ff5 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksNotification.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksNotification.scala @@ -10,6 +10,7 @@ import android.support.v4.app.NotificationCompat.BigTextStyle import android.support.v4.content.ContextCompat import com.github.shadowsocks.aidl.IShadowsocksServiceCallback.Stub import com.github.shadowsocks.utils.{TrafficMonitor, Action, State, Utils} +import com.github.shadowsocks.ShadowsocksApplication.app /** * @author Mygod @@ -41,7 +42,7 @@ class ShadowsocksNotification(private val service: BaseService, profileName: Str .setSmallIcon(R.drawable.ic_stat_shadowsocks) .addAction(R.drawable.ic_navigation_close, service.getString(R.string.stop), PendingIntent.getBroadcast(service, 0, new Intent(Action.CLOSE), 0)) - ShadowsocksApplication.profileManager.getAllProfiles match { + app.profileManager.getAllProfiles match { case Some(profiles) => if (profiles.length > 1) builder.addAction(R.drawable.ic_action_settings, service.getString(R.string.quick_switch), PendingIntent.getActivity(service, 0, new Intent(Action.QUICK_SWITCH), 0)) diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksQuickSwitchActivity.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksQuickSwitchActivity.scala index 962f3a9f..3a632bb1 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksQuickSwitchActivity.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksQuickSwitchActivity.scala @@ -8,6 +8,7 @@ import android.view.{LayoutInflater, View, ViewGroup} import android.widget.CheckedTextView import com.github.shadowsocks.database.Profile import com.github.shadowsocks.utils.Utils +import com.github.shadowsocks.ShadowsocksApplication.app /** * Created by Lucas on 3/10/16. @@ -27,18 +28,18 @@ class ShadowsocksQuickSwitchActivity extends AppCompatActivity { def bind(item: Profile) { this.item = item text.setText(item.name) - text.setChecked(item.id == ShadowsocksApplication.profileId) + text.setChecked(item.id == app.profileId) } def onClick(v: View) { - ShadowsocksApplication.switchProfile(item.id) + app.switchProfile(item.id) Utils.startSsService(ShadowsocksQuickSwitchActivity.this) finish } } private class ProfilesAdapter extends RecyclerView.Adapter[ProfileViewHolder] { - val profiles = ShadowsocksApplication.profileManager.getAllProfiles.getOrElse(List.empty[Profile]) + val profiles = app.profileManager.getAllProfiles.getOrElse(List.empty[Profile]) def getItemCount = profiles.length @@ -66,8 +67,8 @@ class ShadowsocksQuickSwitchActivity extends AppCompatActivity { profilesList.setLayoutManager(lm) profilesList.setItemAnimator(new DefaultItemAnimator) profilesList.setAdapter(profilesAdapter) - if (ShadowsocksApplication.profileId >= 0) lm.scrollToPosition(profilesAdapter.profiles.zipWithIndex.collectFirst { - case (profile, i) if profile.id == ShadowsocksApplication.profileId => i + 1 + if (app.profileId >= 0) lm.scrollToPosition(profilesAdapter.profiles.zipWithIndex.collectFirst { + case (profile, i) if profile.id == app.profileId => i + 1 }.getOrElse(0)) } } diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksRunnerActivity.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksRunnerActivity.scala index d8e04a29..dd6f7e82 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksRunnerActivity.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksRunnerActivity.scala @@ -45,6 +45,7 @@ import android.net.VpnService import android.os.{Bundle, Handler} import android.util.Log import com.github.shadowsocks.utils.ConfigUtils +import com.github.shadowsocks.ShadowsocksApplication.app object ShadowsocksRunnerActivity { private final val TAG = "ShadowsocksRunnerActivity" @@ -64,7 +65,7 @@ class ShadowsocksRunnerActivity extends Activity with ServiceBoundContext { } def startBackgroundService() { - if (ShadowsocksApplication.isVpnEnabled) { + if (app.isVpnEnabled) { val intent = VpnService.prepare(ShadowsocksRunnerActivity.this) if (intent != null) { startActivityForResult(intent, REQUEST_CONNECT) @@ -72,7 +73,7 @@ class ShadowsocksRunnerActivity extends Activity with ServiceBoundContext { onActivityResult(REQUEST_CONNECT, Activity.RESULT_OK, null) } } else { - bgService.use(ConfigUtils.load(ShadowsocksApplication.settings)) + bgService.use(ConfigUtils.load(app.settings)) finish() } } @@ -108,7 +109,7 @@ class ShadowsocksRunnerActivity extends Activity with ServiceBoundContext { resultCode match { case Activity.RESULT_OK => if (bgService != null) { - bgService.use(ConfigUtils.load(ShadowsocksApplication.settings)) + bgService.use(ConfigUtils.load(app.settings)) } case _ => Log.e(TAG, "Failed to start VpnService") diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksRunnerService.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksRunnerService.scala index 1c779ca1..078075ed 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksRunnerService.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksRunnerService.scala @@ -44,6 +44,7 @@ import android.content.Intent import android.net.VpnService import android.os.{IBinder, Handler} import com.github.shadowsocks.utils.ConfigUtils +import com.github.shadowsocks.ShadowsocksApplication.app class ShadowsocksRunnerService extends Service with ServiceBoundContext { val handler = new Handler() @@ -57,15 +58,15 @@ class ShadowsocksRunnerService extends Service with ServiceBoundContext { } def startBackgroundService() { - if (ShadowsocksApplication.isVpnEnabled) { + if (app.isVpnEnabled) { val intent = VpnService.prepare(ShadowsocksRunnerService.this) if (intent == null) { if (bgService != null) { - bgService.use(ConfigUtils.load(ShadowsocksApplication.settings)) + bgService.use(ConfigUtils.load(app.settings)) } } } else { - bgService.use(ConfigUtils.load(ShadowsocksApplication.settings)) + bgService.use(ConfigUtils.load(app.settings)) } stopSelf() } diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksSettings.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksSettings.scala index a9399e18..b57dded7 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksSettings.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksSettings.scala @@ -12,6 +12,7 @@ import android.webkit.{WebView, WebViewClient} import com.github.shadowsocks.database.Profile import com.github.shadowsocks.preferences._ import com.github.shadowsocks.utils.{Key, Utils} +import com.github.shadowsocks.ShadowsocksApplication.app object ShadowsocksSettings { // Constants @@ -92,7 +93,7 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan switch.setChecked(BootReceiver.getEnabled(activity)) findPreference("recovery").setOnPreferenceClickListener((preference: Preference) => { - ShadowsocksApplication.track(TAG, "reset") + app.track(TAG, "reset") activity.recovery() true }) @@ -100,13 +101,13 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan val flush = findPreference("flush_dnscache") if (Build.VERSION.SDK_INT < 17) flush.setSummary(R.string.flush_dnscache_summary) flush.setOnPreferenceClickListener(_ => { - ShadowsocksApplication.track(TAG, "flush_dnscache") + app.track(TAG, "flush_dnscache") activity.flushDnsCache() true }) findPreference("about").setOnPreferenceClickListener((preference: Preference) => { - ShadowsocksApplication.track(TAG, "about") + app.track(TAG, "about") val web = new WebView(activity) web.loadUrl("file:///android_asset/pages/about.html") web.setWebViewClient(new WebViewClient() { @@ -121,7 +122,7 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan }) new AlertDialog.Builder(activity) - .setTitle(getString(R.string.about_title).formatLocal(Locale.ENGLISH, ShadowsocksApplication.getVersionName)) + .setTitle(getString(R.string.about_title).formatLocal(Locale.ENGLISH, app.getVersionName)) .setNegativeButton(getString(android.R.string.ok), null) .setView(web) .create() @@ -132,12 +133,12 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan override def onResume { super.onResume() - isProxyApps.setChecked(ShadowsocksApplication.settings.getBoolean(Key.isProxyApps, false)) // update + isProxyApps.setChecked(app.settings.getBoolean(Key.isProxyApps, false)) // update } override def onDestroy { super.onDestroy() - ShadowsocksApplication.settings.unregisterOnSharedPreferenceChangeListener(this) + app.settings.unregisterOnSharedPreferenceChangeListener(this) } def onSharedPreferenceChanged(pref: SharedPreferences, key: String) = key match { @@ -155,7 +156,7 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan for (name <- Key.isNAT #:: PROXY_PREFS.toStream #::: FEATURE_PREFS.toStream) { val pref = findPreference(name) if (pref != null) pref.setEnabled(enabled && - (name != Key.isProxyApps || Utils.isLollipopOrAbove || !ShadowsocksApplication.isVpnEnabled)) + (name != Key.isProxyApps || Utils.isLollipopOrAbove || !app.isVpnEnabled)) } } diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala index bdacacfa..70335edf 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala @@ -50,6 +50,7 @@ import android.os._ import android.util.Log import com.github.shadowsocks.aidl.Config import com.github.shadowsocks.utils._ +import com.github.shadowsocks.ShadowsocksApplication.app import scala.collection.mutable.ArrayBuffer @@ -98,7 +99,7 @@ class ShadowsocksVpnService extends VpnService with BaseService { // channge the state changeState(State.STOPPING) - ShadowsocksApplication.track(TAG, "stop") + app.track(TAG, "stop") // reset VPN killProcesses() @@ -146,13 +147,13 @@ class ShadowsocksVpnService extends VpnService with BaseService { return } - ShadowsocksApplication.track(TAG, "start") + app.track(TAG, "start") changeState(State.CONNECTING) Utils.ThrowableFuture { if (config.proxy == "198.199.101.152") { - val holder = ShadowsocksApplication.containerHolder + val holder = app.containerHolder try { this.config = ConfigUtils.getPublicConfig(getBaseContext, holder.getContainer, config) } catch { diff --git a/src/main/scala/com/github/shadowsocks/TaskerActivity.scala b/src/main/scala/com/github/shadowsocks/TaskerActivity.scala index f6461e22..05c0d5e2 100644 --- a/src/main/scala/com/github/shadowsocks/TaskerActivity.scala +++ b/src/main/scala/com/github/shadowsocks/TaskerActivity.scala @@ -47,6 +47,7 @@ import android.view.{LayoutInflater, View, ViewGroup} import android.widget.{CheckedTextView, Switch} import com.github.shadowsocks.database.Profile import com.github.shadowsocks.utils.TaskerSettings +import com.github.shadowsocks.ShadowsocksApplication.app /** * @author CzBiX @@ -82,7 +83,7 @@ class TaskerActivity extends AppCompatActivity { } private class ProfilesAdapter extends RecyclerView.Adapter[ProfileViewHolder] { - val profiles = ShadowsocksApplication.profileManager.getAllProfiles.getOrElse(List.empty[Profile]) + val profiles = app.profileManager.getAllProfiles.getOrElse(List.empty[Profile]) def getItemCount = 1 + profiles.length def onBindViewHolder(vh: ProfileViewHolder, i: Int) = i match { case 0 => vh.bindDefault diff --git a/src/main/scala/com/github/shadowsocks/TaskerReceiver.scala b/src/main/scala/com/github/shadowsocks/TaskerReceiver.scala index f321cb5e..94b8e5d1 100644 --- a/src/main/scala/com/github/shadowsocks/TaskerReceiver.scala +++ b/src/main/scala/com/github/shadowsocks/TaskerReceiver.scala @@ -40,6 +40,7 @@ package com.github.shadowsocks import android.content.{BroadcastReceiver, Context, Intent} import com.github.shadowsocks.utils.{TaskerSettings, Utils} +import com.github.shadowsocks.ShadowsocksApplication.app /** * @author CzBiX @@ -47,9 +48,9 @@ import com.github.shadowsocks.utils.{TaskerSettings, Utils} class TaskerReceiver extends BroadcastReceiver { override def onReceive(context: Context, intent: Intent) { val settings = TaskerSettings.fromIntent(intent) - val switched = ShadowsocksApplication.profileManager.getProfile(settings.profileId) match { + val switched = app.profileManager.getProfile(settings.profileId) match { case Some(p) => - ShadowsocksApplication.switchProfile(settings.profileId) + app.switchProfile(settings.profileId) true case _ => false } diff --git a/src/main/scala/com/github/shadowsocks/database/ProfileManager.scala b/src/main/scala/com/github/shadowsocks/database/ProfileManager.scala index bcb39878..a56d0664 100644 --- a/src/main/scala/com/github/shadowsocks/database/ProfileManager.scala +++ b/src/main/scala/com/github/shadowsocks/database/ProfileManager.scala @@ -41,7 +41,7 @@ package com.github.shadowsocks.database import android.content.SharedPreferences import android.util.Log -import com.github.shadowsocks._ +import com.github.shadowsocks.ShadowsocksApplication.app import com.github.shadowsocks.utils.Key object ProfileManager { @@ -58,7 +58,7 @@ class ProfileManager(settings: SharedPreferences, dbHelper: DBHelper) { try { val profile = if (p == null) new Profile else p profile.id = 0 - ShadowsocksApplication.currentProfile match { + app.currentProfile match { case Some(oldProfile) => // Copy Feature Settings from old profile profile.route = oldProfile.route diff --git a/src/main/scala/com/github/shadowsocks/utils/ConfigUtils.scala b/src/main/scala/com/github/shadowsocks/utils/ConfigUtils.scala index 89adfd1c..303c9d9e 100644 --- a/src/main/scala/com/github/shadowsocks/utils/ConfigUtils.scala +++ b/src/main/scala/com/github/shadowsocks/utils/ConfigUtils.scala @@ -39,11 +39,12 @@ package com.github.shadowsocks.utils -import android.content.{SharedPreferences, Context} -import com.github.shadowsocks.{R, ShadowsocksApplication} -import com.google.android.gms.tagmanager.Container +import android.content.{Context, SharedPreferences} import com.github.kevinsawicki.http.HttpRequest +import com.github.shadowsocks.R +import com.github.shadowsocks.ShadowsocksApplication.app import com.github.shadowsocks.aidl.Config +import com.google.android.gms.tagmanager.Container object ConfigUtils { val SHADOWSOCKS = "{\"server\": \"%s\", \"server_port\": %d, \"local_port\": %d, \"password\": \"%s\", \"method\":\"%s\", \"timeout\": %d}" @@ -152,14 +153,14 @@ object ConfigUtils { } def refresh(context: Context) { - val holder = ShadowsocksApplication.containerHolder + val holder = app.containerHolder if (holder != null) holder.refresh() } def getRejectList(context: Context): String = { val default = context.getString(R.string.reject) try { - val container = ShadowsocksApplication.containerHolder.getContainer + val container = app.containerHolder.getContainer val update = container.getString("reject") if (update == null || update.isEmpty) default else update } catch { @@ -170,7 +171,7 @@ object ConfigUtils { def getBlackList(context: Context): String = { val default = context.getString(R.string.black_list) try { - val container = ShadowsocksApplication.containerHolder.getContainer + val container = app.containerHolder.getContainer val update = container.getString("black_list") if (update == null || update.isEmpty) default else update } catch { diff --git a/src/main/scala/com/github/shadowsocks/utils/TaskerSettings.scala b/src/main/scala/com/github/shadowsocks/utils/TaskerSettings.scala index 79434770..550dc0f0 100644 --- a/src/main/scala/com/github/shadowsocks/utils/TaskerSettings.scala +++ b/src/main/scala/com/github/shadowsocks/utils/TaskerSettings.scala @@ -40,7 +40,8 @@ package com.github.shadowsocks.utils import android.content.{Context, Intent} import android.os.Bundle -import com.github.shadowsocks.{R, ShadowsocksApplication} +import com.github.shadowsocks.R +import com.github.shadowsocks.ShadowsocksApplication.app import com.twofortyfouram.locale.api.{Intent => ApiIntent} object TaskerSettings { @@ -62,7 +63,7 @@ class TaskerSettings(bundle: Bundle) { if (!switchOn) bundle.putBoolean(KEY_SWITCH_ON, false) if (profileId >= 0) bundle.putInt(KEY_PROFILE_ID, profileId) new Intent().putExtra(ApiIntent.EXTRA_BUNDLE, bundle).putExtra(ApiIntent.EXTRA_STRING_BLURB, - ShadowsocksApplication.profileManager.getProfile(profileId) match { + app.profileManager.getProfile(profileId) match { case Some(p) => context.getString(if (switchOn) R.string.start_service else R.string.stop_service, p.name) case None => context.getString(if (switchOn) R.string.start_service_default else R.string.stop) }) diff --git a/src/main/scala/com/github/shadowsocks/utils/TrafficMonitor.scala b/src/main/scala/com/github/shadowsocks/utils/TrafficMonitor.scala index f84015b6..9849b58d 100644 --- a/src/main/scala/com/github/shadowsocks/utils/TrafficMonitor.scala +++ b/src/main/scala/com/github/shadowsocks/utils/TrafficMonitor.scala @@ -2,7 +2,8 @@ package com.github.shadowsocks.utils import java.text.DecimalFormat -import com.github.shadowsocks.{R, ShadowsocksApplication} +import com.github.shadowsocks.R +import com.github.shadowsocks.ShadowsocksApplication.app object TrafficMonitor { // Bytes per second @@ -28,7 +29,7 @@ object TrafficMonitor { n /= 1024 i = i + 1 } - if (i < 0) size + " " + ShadowsocksApplication.instance.getResources.getQuantityString(R.plurals.bytes, size.toInt) + if (i < 0) size + " " + app.getResources.getQuantityString(R.plurals.bytes, size.toInt) else numberFormat.format(n) + ' ' + units(i) } diff --git a/src/main/scala/com/github/shadowsocks/utils/Utils.scala b/src/main/scala/com/github/shadowsocks/utils/Utils.scala index 3b294514..7305988a 100644 --- a/src/main/scala/com/github/shadowsocks/utils/Utils.scala +++ b/src/main/scala/com/github/shadowsocks/utils/Utils.scala @@ -51,7 +51,8 @@ import android.util.{Base64, DisplayMetrics, Log} import android.view.View.MeasureSpec import android.view.{Gravity, View, Window} import android.widget.Toast -import com.github.shadowsocks.{BuildConfig, ShadowsocksApplication, ShadowsocksRunnerService} +import com.github.shadowsocks.ShadowsocksApplication.app +import com.github.shadowsocks.{BuildConfig, ShadowsocksRunnerService} import org.xbill.DNS._ import scala.concurrent.ExecutionContext.Implicits.global @@ -59,7 +60,6 @@ import scala.concurrent.Future import scala.util.{Failure, Try} object Utils { - private val TAG = "Shadowsocks" /** @@ -229,7 +229,7 @@ object Utils { } def startSsService(context: Context) { - val isInstalled: Boolean = ShadowsocksApplication.settings.getBoolean(ShadowsocksApplication.getVersionName, false) + val isInstalled: Boolean = app.settings.getBoolean(app.getVersionName, false) if (!isInstalled) return val intent = new Intent(context, classOf[ShadowsocksRunnerService])