Refine code style
This commit is contained in:
@@ -37,7 +37,7 @@ class EditTextPreference(context: Context, attrs: AttributeSet = null) extends P
|
||||
|
||||
override def createDialog() = new EditTextPreferenceDialogFragment()
|
||||
|
||||
override protected def getSummaryValue = {
|
||||
override protected def getSummaryValue: String = {
|
||||
var text = getText
|
||||
if (text == null) text = ""
|
||||
val inputType = editText.getInputType
|
||||
@@ -47,8 +47,8 @@ class EditTextPreference(context: Context, attrs: AttributeSet = null) extends P
|
||||
"\u2022" * text.length else text
|
||||
}
|
||||
|
||||
override def setText(text: String) = {
|
||||
override def setText(text: String): Unit = {
|
||||
super.setText(text)
|
||||
notifyChanged
|
||||
notifyChanged()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,13 +22,14 @@ package be.mygod.preference
|
||||
|
||||
import android.content.Context
|
||||
import android.support.v14.preference.PreferenceDialogFragment
|
||||
import android.support.v7.widget.AppCompatEditText
|
||||
import android.view.{View, ViewGroup}
|
||||
|
||||
class EditTextPreferenceDialogFragment extends PreferenceDialogFragment {
|
||||
private lazy val preference = getPreference.asInstanceOf[EditTextPreference]
|
||||
private lazy val editText = preference.editText
|
||||
|
||||
override protected def onCreateDialogView(context: Context) = {
|
||||
override protected def onCreateDialogView(context: Context): AppCompatEditText = {
|
||||
val parent = editText.getParent.asInstanceOf[ViewGroup]
|
||||
if (parent != null) parent.removeView(editText)
|
||||
editText
|
||||
@@ -43,7 +44,7 @@ class EditTextPreferenceDialogFragment extends PreferenceDialogFragment {
|
||||
|
||||
override protected def needInputMethod = true
|
||||
|
||||
def onDialogClosed(positiveResult: Boolean) = if (positiveResult) {
|
||||
def onDialogClosed(positiveResult: Boolean): Unit = if (positiveResult) {
|
||||
val value = editText.getText.toString
|
||||
if (preference.callChangeListener(value)) preference.setText(value)
|
||||
}
|
||||
|
||||
@@ -37,23 +37,23 @@ class NumberPickerPreference(private val context: Context, attrs: AttributeSet =
|
||||
val a: TypedArray = context.obtainStyledAttributes(attrs, R.styleable.NumberPickerPreference)
|
||||
setMin(a.getInt(R.styleable.NumberPickerPreference_min, 0))
|
||||
setMax(a.getInt(R.styleable.NumberPickerPreference_max, Int.MaxValue - 1))
|
||||
a.recycle
|
||||
a.recycle()
|
||||
}
|
||||
|
||||
override def createDialog() = new NumberPickerPreferenceDialogFragment()
|
||||
|
||||
def getValue = value
|
||||
def getMin = if (picker == null) 0 else picker.getMinValue
|
||||
def getMax = picker.getMaxValue
|
||||
def getValue: Int = value
|
||||
def getMin: Int = if (picker == null) 0 else picker.getMinValue
|
||||
def getMax: Int = picker.getMaxValue
|
||||
def setValue(i: Int) {
|
||||
if (i == value) return
|
||||
picker.setValue(i)
|
||||
value = picker.getValue
|
||||
persistInt(value)
|
||||
notifyChanged
|
||||
notifyChanged()
|
||||
}
|
||||
def setMin(value: Int) = picker.setMinValue(value)
|
||||
def setMax(value: Int) = picker.setMaxValue(value)
|
||||
def setMin(value: Int): Unit = picker.setMinValue(value)
|
||||
def setMax(value: Int): Unit = picker.setMaxValue(value)
|
||||
|
||||
override protected def onGetDefaultValue(a: TypedArray, index: Int): AnyRef =
|
||||
a.getInt(index, getMin).asInstanceOf[AnyRef]
|
||||
|
||||
@@ -23,12 +23,13 @@ package be.mygod.preference
|
||||
import android.content.Context
|
||||
import android.support.v14.preference.PreferenceDialogFragment
|
||||
import android.view.{View, ViewGroup}
|
||||
import android.widget.NumberPicker
|
||||
|
||||
class NumberPickerPreferenceDialogFragment extends PreferenceDialogFragment {
|
||||
private lazy val preference = getPreference.asInstanceOf[NumberPickerPreference]
|
||||
private lazy val picker = preference.picker
|
||||
|
||||
override protected def onCreateDialogView(context: Context) = {
|
||||
override protected def onCreateDialogView(context: Context): NumberPicker = {
|
||||
val parent = picker.getParent.asInstanceOf[ViewGroup]
|
||||
if (parent != null) parent.removeView(picker)
|
||||
picker
|
||||
@@ -42,7 +43,7 @@ class NumberPickerPreferenceDialogFragment extends PreferenceDialogFragment {
|
||||
override protected def needInputMethod = true
|
||||
|
||||
def onDialogClosed(positiveResult: Boolean) {
|
||||
picker.clearFocus // commit changes
|
||||
picker.clearFocus() // commit changes
|
||||
if (positiveResult) {
|
||||
val value = picker.getValue
|
||||
if (preference.callChangeListener(value)) preference.setValue(value)
|
||||
|
||||
@@ -24,10 +24,10 @@ import android.app.DialogFragment
|
||||
import android.os.Bundle
|
||||
import android.support.v14.preference.{PreferenceFragment => Base}
|
||||
import android.support.v7.preference.{Preference, PreferenceScreen}
|
||||
import android.view.{LayoutInflater, ViewGroup}
|
||||
import android.view.{LayoutInflater, View, ViewGroup}
|
||||
|
||||
abstract class PreferenceFragment extends Base {
|
||||
override def onCreateView(inflater: LayoutInflater, container: ViewGroup, savedInstanceState: Bundle) =
|
||||
override def onCreateView(inflater: LayoutInflater, container: ViewGroup, savedInstanceState: Bundle): View =
|
||||
super.onCreateView(inflater, container, savedInstanceState)
|
||||
|
||||
protected final def displayPreferenceDialog(key: String, fragment: DialogFragment) {
|
||||
@@ -40,15 +40,15 @@ abstract class PreferenceFragment extends Base {
|
||||
.commitAllowingStateLoss()
|
||||
}
|
||||
|
||||
override def onDisplayPreferenceDialog(preference: Preference) = preference match {
|
||||
override def onDisplayPreferenceDialog(preference: Preference): Unit = preference match {
|
||||
case dpp: DialogPreferencePlus => displayPreferenceDialog(preference.getKey, dpp.createDialog())
|
||||
case _ => super.onDisplayPreferenceDialog(preference)
|
||||
}
|
||||
|
||||
override protected def onCreateAdapter(screen: PreferenceScreen) = new PreferenceGroupAdapter(screen)
|
||||
|
||||
override def onResume {
|
||||
super.onResume
|
||||
override def onResume() {
|
||||
super.onResume()
|
||||
getListView.scrollBy(0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
package be.mygod.preference
|
||||
|
||||
import java.lang.reflect.Field
|
||||
import java.util.List
|
||||
import java.util
|
||||
|
||||
import android.os.Build
|
||||
import android.support.v4.content.ContextCompat
|
||||
@@ -57,29 +57,31 @@ object PreferenceGroupAdapter {
|
||||
class PreferenceGroupAdapter(group: PreferenceGroup) extends Old(group) {
|
||||
import PreferenceGroupAdapter._
|
||||
|
||||
protected lazy val preferenceLayouts = preferenceLayoutsField.get(this).asInstanceOf[List[AnyRef]]
|
||||
protected lazy val preferenceLayouts: util.List[AnyRef] =
|
||||
preferenceLayoutsField.get(this).asInstanceOf[util.List[AnyRef]]
|
||||
|
||||
override def onCreateViewHolder(parent: ViewGroup, viewType: Int) = if (Build.VERSION.SDK_INT < 21) {
|
||||
val context = parent.getContext
|
||||
val inflater = LayoutInflater.from(context)
|
||||
val pl = preferenceLayouts.get(viewType)
|
||||
val view = inflater.inflate(fieldResId.get(pl).asInstanceOf[Int], parent, false)
|
||||
if (view.getBackground == null) {
|
||||
val array = context.obtainStyledAttributes(null, R.styleable.BackgroundStyle)
|
||||
var background = array.getDrawable(R.styleable.BackgroundStyle_android_selectableItemBackground)
|
||||
if (background == null)
|
||||
background = ContextCompat.getDrawable(context, android.R.drawable.list_selector_background)
|
||||
array.recycle
|
||||
val (s, t, e, b) = (ViewCompat.getPaddingStart(view), view.getPaddingTop,
|
||||
ViewCompat.getPaddingEnd(view), view.getPaddingBottom)
|
||||
view.setBackground(background)
|
||||
ViewCompat.setPaddingRelative(view, s, t, e, b)
|
||||
}
|
||||
val widgetFrame = view.findViewById(android.R.id.widget_frame).asInstanceOf[ViewGroup]
|
||||
if (widgetFrame != null) {
|
||||
val widgetResId = fieldWidgetResId.get(pl).asInstanceOf[Int]
|
||||
if (widgetResId != 0) inflater.inflate(widgetResId, widgetFrame) else widgetFrame.setVisibility(View.GONE)
|
||||
}
|
||||
preferenceViewHolderConstructor.newInstance(view)
|
||||
} else super.onCreateViewHolder(parent, viewType)
|
||||
override def onCreateViewHolder(parent: ViewGroup, viewType: Int): PreferenceViewHolder =
|
||||
if (Build.VERSION.SDK_INT < 21) {
|
||||
val context = parent.getContext
|
||||
val inflater = LayoutInflater.from(context)
|
||||
val pl = preferenceLayouts.get(viewType)
|
||||
val view = inflater.inflate(fieldResId.get(pl).asInstanceOf[Int], parent, false)
|
||||
if (view.getBackground == null) {
|
||||
val array = context.obtainStyledAttributes(null, R.styleable.BackgroundStyle)
|
||||
var background = array.getDrawable(R.styleable.BackgroundStyle_android_selectableItemBackground)
|
||||
if (background == null)
|
||||
background = ContextCompat.getDrawable(context, android.R.drawable.list_selector_background)
|
||||
array.recycle()
|
||||
val (s, t, e, b) = (ViewCompat.getPaddingStart(view), view.getPaddingTop,
|
||||
ViewCompat.getPaddingEnd(view), view.getPaddingBottom)
|
||||
view.setBackground(background)
|
||||
ViewCompat.setPaddingRelative(view, s, t, e, b)
|
||||
}
|
||||
val widgetFrame = view.findViewById(android.R.id.widget_frame).asInstanceOf[ViewGroup]
|
||||
if (widgetFrame != null) {
|
||||
val widgetResId = fieldWidgetResId.get(pl).asInstanceOf[Int]
|
||||
if (widgetResId != 0) inflater.inflate(widgetResId, widgetFrame) else widgetFrame.setVisibility(View.GONE)
|
||||
}
|
||||
preferenceViewHolderConstructor.newInstance(view)
|
||||
} else super.onCreateViewHolder(parent, viewType)
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ trait SummaryPreference extends Preference {
|
||||
*
|
||||
* @return the summary with appropriate string substitution
|
||||
*/
|
||||
override def getSummary = {
|
||||
override def getSummary: String = {
|
||||
val summary = super.getSummary
|
||||
if (summary == null) null else String.format(summary.toString, getSummaryValue)
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ object AppManager {
|
||||
val filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED)
|
||||
filter.addAction(Intent.ACTION_PACKAGE_REMOVED)
|
||||
filter.addDataScheme("package")
|
||||
app.registerReceiver((context: Context, intent: Intent) =>
|
||||
app.registerReceiver((_: Context, intent: Intent) =>
|
||||
if (intent.getAction != Intent.ACTION_PACKAGE_REMOVED ||
|
||||
!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
|
||||
synchronized(cachedApps = null)
|
||||
@@ -111,8 +111,8 @@ class AppManager extends AppCompatActivity with OnMenuItemClickListener {
|
||||
if (aProxied ^ proxiedApps.contains(b.packageName)) aProxied else a.name.compareToIgnoreCase(b.name) < 0
|
||||
})
|
||||
|
||||
def getItemCount = apps.length
|
||||
def onBindViewHolder(vh: AppViewHolder, i: Int) = vh.bind(apps(i))
|
||||
def getItemCount: Int = apps.length
|
||||
def onBindViewHolder(vh: AppViewHolder, i: Int): Unit = vh.bind(apps(i))
|
||||
def onCreateViewHolder(vg: ViewGroup, i: Int) =
|
||||
new AppViewHolder(LayoutInflater.from(vg.getContext).inflate(R.layout.layout_apps_item, vg, false))
|
||||
}
|
||||
@@ -148,8 +148,8 @@ class AppManager extends AppCompatActivity with OnMenuItemClickListener {
|
||||
p.individual = proxiedAppString
|
||||
app.profileManager.updateProfile(p)
|
||||
})
|
||||
Toast.makeText(this, R.string.action_apply_all, Toast.LENGTH_SHORT).show
|
||||
case _ => Toast.makeText(this, R.string.action_export_err, Toast.LENGTH_SHORT).show
|
||||
Toast.makeText(this, R.string.action_apply_all, Toast.LENGTH_SHORT).show()
|
||||
case _ => Toast.makeText(this, R.string.action_export_err, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
return true
|
||||
case R.id.action_export =>
|
||||
@@ -180,7 +180,7 @@ class AppManager extends AppCompatActivity with OnMenuItemClickListener {
|
||||
return true
|
||||
} catch {
|
||||
case _: IllegalArgumentException =>
|
||||
Toast.makeText(this, R.string.action_import_err, Toast.LENGTH_SHORT).show
|
||||
Toast.makeText(this, R.string.action_import_err, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -239,7 +239,7 @@ class AppManager extends AppCompatActivity with OnMenuItemClickListener {
|
||||
loadAppsAsync()
|
||||
}
|
||||
|
||||
def reloadApps() = if (!appsLoading.compareAndSet(true, false)) loadAppsAsync()
|
||||
def reloadApps(): Unit = if (!appsLoading.compareAndSet(true, false)) loadAppsAsync()
|
||||
def loadAppsAsync() {
|
||||
if (!appsLoading.compareAndSet(false, true)) return
|
||||
Utils.ThrowableFuture {
|
||||
@@ -255,7 +255,7 @@ class AppManager extends AppCompatActivity with OnMenuItemClickListener {
|
||||
}
|
||||
}
|
||||
|
||||
override def onKeyUp(keyCode: Int, event: KeyEvent) = keyCode match {
|
||||
override def onKeyUp(keyCode: Int, event: KeyEvent): Boolean = keyCode match {
|
||||
case KeyEvent.KEYCODE_MENU =>
|
||||
if (toolbar.isOverflowMenuShowing) toolbar.hideOverflowMenu else toolbar.showOverflowMenu
|
||||
case _ => super.onKeyUp(keyCode, event)
|
||||
|
||||
@@ -52,19 +52,19 @@ trait BaseService extends Service {
|
||||
var callbacksCount: Int = _
|
||||
lazy val handler = new Handler(getMainLooper)
|
||||
lazy val restartHanlder = new Handler(getMainLooper)
|
||||
lazy val protectPath = getApplicationInfo.dataDir + "/protect_path"
|
||||
lazy val protectPath: String = getApplicationInfo.dataDir + "/protect_path"
|
||||
|
||||
private val closeReceiver: BroadcastReceiver = (context: Context, intent: Intent) => {
|
||||
private val closeReceiver: BroadcastReceiver = (context: Context, _: Intent) => {
|
||||
Toast.makeText(context, R.string.stopping, Toast.LENGTH_SHORT).show()
|
||||
stopRunner(true)
|
||||
stopRunner(stopService = true)
|
||||
}
|
||||
var closeReceiverRegistered: Boolean = _
|
||||
|
||||
var kcptunProcess: GuardedProcess = _
|
||||
private val networkReceiver: BroadcastReceiver = (context: Context, intent: Intent) => {
|
||||
private val networkReceiver: BroadcastReceiver = (context: Context, _: Intent) => {
|
||||
val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE).asInstanceOf[ConnectivityManager]
|
||||
val activeNetwork = cm.getActiveNetworkInfo()
|
||||
val isConnected = activeNetwork != null && activeNetwork.isConnected()
|
||||
val activeNetwork = cm.getActiveNetworkInfo
|
||||
val isConnected = activeNetwork != null && activeNetwork.isConnected
|
||||
|
||||
if (isConnected && profile.kcp && kcptunProcess != null) {
|
||||
restartHanlder.removeCallbacks(null)
|
||||
@@ -95,7 +95,7 @@ trait BaseService extends Service {
|
||||
callbacksCount += 1
|
||||
if (callbacksCount != 0 && timer == null) {
|
||||
val task = new TimerTask {
|
||||
def run {
|
||||
def run() {
|
||||
if (TrafficMonitor.updateRate()) updateTrafficRate()
|
||||
}
|
||||
}
|
||||
@@ -107,27 +107,27 @@ trait BaseService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
override def use(profileId: Int) = synchronized(if (profileId < 0) stopRunner(true) else {
|
||||
override def use(profileId: Int): Unit = synchronized(if (profileId < 0) stopRunner(stopService = true) else {
|
||||
val profile = app.profileManager.getProfile(profileId).orNull
|
||||
if (profile == null) stopRunner(true) else state match {
|
||||
if (profile == null) stopRunner(stopService = true) else state match {
|
||||
case State.STOPPED => if (checkProfile(profile)) startRunner(profile)
|
||||
case State.CONNECTED => if (profileId != BaseService.this.profile.id && checkProfile(profile)) {
|
||||
stopRunner(false)
|
||||
stopRunner(stopService = false)
|
||||
startRunner(profile)
|
||||
}
|
||||
case _ => Log.w(BaseService.this.getClass.getSimpleName, "Illegal state when invoking use: " + state)
|
||||
}
|
||||
})
|
||||
|
||||
override def useSync(profileId: Int) = use(profileId)
|
||||
override def useSync(profileId: Int): Unit = use(profileId)
|
||||
}
|
||||
|
||||
def checkProfile(profile: Profile) = if (TextUtils.isEmpty(profile.host) || TextUtils.isEmpty(profile.password)) {
|
||||
stopRunner(true, getString(R.string.proxy_empty))
|
||||
def checkProfile(profile: Profile): Boolean = if (TextUtils.isEmpty(profile.host) || TextUtils.isEmpty(profile.password)) {
|
||||
stopRunner(stopService = true, getString(R.string.proxy_empty))
|
||||
false
|
||||
} else true
|
||||
|
||||
def connect() = if (profile.host == "198.199.101.152") {
|
||||
def connect(): Unit = if (profile.host == "198.199.101.152") {
|
||||
val holder = app.containerHolder
|
||||
val container = holder.getContainer
|
||||
val url = container.getString("proxy_url")
|
||||
@@ -175,15 +175,16 @@ trait BaseService extends Service {
|
||||
|
||||
changeState(State.CONNECTING)
|
||||
|
||||
if (profile.isMethodUnsafe) handler.post(() => Toast.makeText(this, R.string.method_unsafe, Toast.LENGTH_LONG).show)
|
||||
if (profile.isMethodUnsafe)
|
||||
handler.post(() => Toast.makeText(this, R.string.method_unsafe, Toast.LENGTH_LONG).show())
|
||||
|
||||
Utils.ThrowableFuture(try connect catch {
|
||||
case _: NameNotResolvedException => stopRunner(true, getString(R.string.invalid_server))
|
||||
Utils.ThrowableFuture(try connect() catch {
|
||||
case _: NameNotResolvedException => stopRunner(stopService = true, getString(R.string.invalid_server))
|
||||
case exc: KcpcliParseException =>
|
||||
stopRunner(true, getString(R.string.service_failed) + ": " + exc.cause.getMessage)
|
||||
case _: NullConnectionException => stopRunner(true, getString(R.string.reboot_required))
|
||||
stopRunner(stopService = true, getString(R.string.service_failed) + ": " + exc.cause.getMessage)
|
||||
case _: NullConnectionException => stopRunner(stopService = true, getString(R.string.reboot_required))
|
||||
case exc: Throwable =>
|
||||
stopRunner(true, getString(R.string.service_failed) + ": " + exc.getMessage)
|
||||
stopRunner(stopService = true, getString(R.string.service_failed) + ": " + exc.getMessage)
|
||||
exc.printStackTrace()
|
||||
app.track(exc)
|
||||
})
|
||||
@@ -283,7 +284,7 @@ trait BaseService extends Service {
|
||||
})
|
||||
}
|
||||
|
||||
def getBlackList = {
|
||||
def getBlackList: String = {
|
||||
val default = getString(R.string.black_list)
|
||||
try {
|
||||
val container = app.containerHolder.getContainer
|
||||
@@ -291,7 +292,7 @@ trait BaseService extends Service {
|
||||
val list = if (update == null || update.isEmpty) default else update
|
||||
"exclude = " + list + ";"
|
||||
} catch {
|
||||
case ex: Exception => "exclude = " + default + ";"
|
||||
case _: Exception => "exclude = " + default + ";"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,16 +25,16 @@ import android.content.{BroadcastReceiver, ComponentName, Context, Intent}
|
||||
import com.github.shadowsocks.utils._
|
||||
|
||||
object BootReceiver {
|
||||
def getEnabled(context: Context) = PackageManager.COMPONENT_ENABLED_STATE_ENABLED ==
|
||||
def getEnabled(context: Context): Boolean = PackageManager.COMPONENT_ENABLED_STATE_ENABLED ==
|
||||
context.getPackageManager.getComponentEnabledSetting(new ComponentName(context, classOf[BootReceiver]))
|
||||
def setEnabled(context: Context, enabled: Boolean) = context.getPackageManager.setComponentEnabledSetting(
|
||||
def setEnabled(context: Context, enabled: Boolean): Unit = context.getPackageManager.setComponentEnabledSetting(
|
||||
new ComponentName(context, classOf[BootReceiver]),
|
||||
if (enabled) PackageManager.COMPONENT_ENABLED_STATE_ENABLED else PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
|
||||
PackageManager.DONT_KILL_APP)
|
||||
}
|
||||
|
||||
class BootReceiver extends BroadcastReceiver {
|
||||
def onReceive(context: Context, intent: Intent) = {
|
||||
def onReceive(context: Context, intent: Intent): Unit = {
|
||||
Utils.startSsService(context)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,24 +25,16 @@ import java.lang.System.currentTimeMillis
|
||||
import java.util.concurrent.Semaphore
|
||||
|
||||
import android.util.Log
|
||||
import com.github.shadowsocks.utils.CloseUtils._
|
||||
|
||||
import scala.collection.JavaConversions._
|
||||
import scala.collection.immutable.Stream
|
||||
import scala.util.control.Exception._
|
||||
|
||||
class StreamLogger(is: InputStream, tag: String) extends Thread {
|
||||
|
||||
def withCloseable[T <: Closeable, R](t: T)(f: T => R): R = {
|
||||
allCatch.andFinally{t.close} apply { f(t) }
|
||||
}
|
||||
|
||||
override def run() {
|
||||
withCloseable(new BufferedReader(new InputStreamReader(is))) {
|
||||
br => try Stream.continually(br.readLine()).takeWhile(_ != null).foreach(Log.i(tag, _)) catch {
|
||||
case ignore: IOException =>
|
||||
}
|
||||
}
|
||||
}
|
||||
override def run(): Unit = autoClose(new BufferedReader(new InputStreamReader(is)))(br =>
|
||||
try Stream.continually(br.readLine()).takeWhile(_ != null).foreach(Log.i(tag, _)) catch {
|
||||
case _: IOException =>
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,7 +50,7 @@ class GuardedProcess(cmd: Seq[String]) {
|
||||
|
||||
def start(onRestartCallback: () => Unit = null): GuardedProcess = {
|
||||
val semaphore = new Semaphore(1)
|
||||
semaphore.acquire
|
||||
semaphore.acquire()
|
||||
@volatile var ioException: IOException = null
|
||||
|
||||
guardThread = new Thread(() => {
|
||||
@@ -71,11 +63,11 @@ class GuardedProcess(cmd: Seq[String]) {
|
||||
process = new ProcessBuilder(cmd).redirectErrorStream(true).start
|
||||
|
||||
val is = process.getInputStream
|
||||
new StreamLogger(is, TAG).start
|
||||
new StreamLogger(is, TAG).start()
|
||||
|
||||
if (callback == null) callback = onRestartCallback else callback()
|
||||
|
||||
semaphore.release
|
||||
semaphore.release()
|
||||
process.waitFor
|
||||
|
||||
this.synchronized {
|
||||
@@ -88,22 +80,19 @@ class GuardedProcess(cmd: Seq[String]) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} catch {
|
||||
case ignored: InterruptedException =>
|
||||
case _: InterruptedException =>
|
||||
Log.i(TAG, "thread interrupt, destroy process: " + cmd)
|
||||
process.destroy()
|
||||
case e: IOException => ioException = e
|
||||
} finally semaphore.release
|
||||
} finally semaphore.release()
|
||||
}, "GuardThread-" + cmd)
|
||||
|
||||
guardThread.start()
|
||||
semaphore.acquire
|
||||
semaphore.acquire()
|
||||
|
||||
if (ioException != null) {
|
||||
throw ioException
|
||||
}
|
||||
if (ioException != null) throw ioException
|
||||
|
||||
this
|
||||
}
|
||||
@@ -113,7 +102,7 @@ class GuardedProcess(cmd: Seq[String]) {
|
||||
guardThread.interrupt()
|
||||
process.destroy()
|
||||
try guardThread.join() catch {
|
||||
case ignored: InterruptedException =>
|
||||
case _: InterruptedException =>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,7 +114,7 @@ class GuardedProcess(cmd: Seq[String]) {
|
||||
}
|
||||
|
||||
@throws(classOf[InterruptedException])
|
||||
def waitFor = {
|
||||
def waitFor: Int = {
|
||||
guardThread.join()
|
||||
0
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ package com.github.shadowsocks
|
||||
|
||||
import java.nio.charset.Charset
|
||||
|
||||
import android.app.{Activity, TaskStackBuilder}
|
||||
import android.app.TaskStackBuilder
|
||||
import android.content._
|
||||
import android.content.pm.PackageManager
|
||||
import android.nfc.NfcAdapter.CreateNdefMessageCallback
|
||||
@@ -97,7 +97,7 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic
|
||||
})
|
||||
shareBtn.setOnLongClickListener(_ => {
|
||||
Utils.positionToast(Toast.makeText(ProfileManagerActivity.this, R.string.share, Toast.LENGTH_SHORT), shareBtn,
|
||||
getWindow, 0, Utils.dpToPx(ProfileManagerActivity.this, 8)).show
|
||||
getWindow, 0, Utils.dpToPx(ProfileManagerActivity.this, 8)).show()
|
||||
true
|
||||
})
|
||||
}
|
||||
@@ -131,41 +131,42 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic
|
||||
|
||||
def onClick(v: View) {
|
||||
app.switchProfile(item.id)
|
||||
finish
|
||||
finish()
|
||||
}
|
||||
|
||||
def onKey(v: View, keyCode: Int, event: KeyEvent) = if (event.getAction == KeyEvent.ACTION_DOWN) keyCode match {
|
||||
case KeyEvent.KEYCODE_DPAD_LEFT =>
|
||||
val index = getAdapterPosition
|
||||
if (index >= 0) {
|
||||
profilesAdapter.remove(index)
|
||||
undoManager.remove(index, item)
|
||||
true
|
||||
} else false
|
||||
case _ => false
|
||||
} else false
|
||||
def onKey(v: View, keyCode: Int, event: KeyEvent): Boolean =
|
||||
if (event.getAction == KeyEvent.ACTION_DOWN) keyCode match {
|
||||
case KeyEvent.KEYCODE_DPAD_LEFT =>
|
||||
val index = getAdapterPosition
|
||||
if (index >= 0) {
|
||||
profilesAdapter.remove(index)
|
||||
undoManager.remove(index, item)
|
||||
true
|
||||
} else false
|
||||
case _ => false
|
||||
} else false
|
||||
}
|
||||
|
||||
private class ProfilesAdapter extends RecyclerView.Adapter[ProfileViewHolder] {
|
||||
var profiles = new ArrayBuffer[Profile]
|
||||
profiles ++= app.profileManager.getAllProfiles.getOrElse(List.empty[Profile])
|
||||
|
||||
def getItemCount = profiles.length
|
||||
def getItemCount: Int = profiles.length
|
||||
|
||||
def onBindViewHolder(vh: ProfileViewHolder, i: Int) = vh.bind(profiles(i))
|
||||
def onBindViewHolder(vh: ProfileViewHolder, i: Int): Unit = vh.bind(profiles(i))
|
||||
|
||||
def onCreateViewHolder(vg: ViewGroup, i: Int) =
|
||||
new ProfileViewHolder(LayoutInflater.from(vg.getContext).inflate(R.layout.layout_profiles_item, vg, false))
|
||||
|
||||
def add(item: Profile) {
|
||||
undoManager.flush
|
||||
undoManager.flush()
|
||||
val pos = getItemCount
|
||||
profiles += item
|
||||
notifyItemInserted(pos)
|
||||
}
|
||||
|
||||
def move(from: Int, to: Int) {
|
||||
undoManager.flush
|
||||
undoManager.flush()
|
||||
val step = if (from < to) 1 else -1
|
||||
val first = profiles(from)
|
||||
var previousOrder = profiles(from).userOrder
|
||||
@@ -187,11 +188,11 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic
|
||||
profiles.remove(pos)
|
||||
notifyItemRemoved(pos)
|
||||
}
|
||||
def undo(actions: Iterator[(Int, Profile)]) = for ((index, item) <- actions) {
|
||||
def undo(actions: Iterator[(Int, Profile)]): Unit = for ((index, item) <- actions) {
|
||||
profiles.insert(index, item)
|
||||
notifyItemInserted(index)
|
||||
}
|
||||
def commit(actions: Iterator[(Int, Profile)]) = for ((index, item) <- actions) {
|
||||
def commit(actions: Iterator[(Int, Profile)]): Unit = for ((_, item) <- actions) {
|
||||
app.profileManager.delProfile(item.id)
|
||||
if (item.id == app.profileId) app.profileId(-1)
|
||||
}
|
||||
@@ -214,8 +215,6 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic
|
||||
private var isNfcEnabled: Boolean = _
|
||||
private var isNfcBeamEnabled: Boolean = _
|
||||
|
||||
private val REQUEST_QRCODE = 1
|
||||
|
||||
override def onCreate(savedInstanceState: Bundle) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.layout_profiles)
|
||||
@@ -246,27 +245,27 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic
|
||||
undoManager = new UndoSnackbarManager[Profile](profilesList, profilesAdapter.undo, profilesAdapter.commit)
|
||||
new ItemTouchHelper(new SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN,
|
||||
ItemTouchHelper.START | ItemTouchHelper.END) {
|
||||
def onSwiped(viewHolder: ViewHolder, direction: Int) = {
|
||||
def onSwiped(viewHolder: ViewHolder, direction: Int) {
|
||||
val index = viewHolder.getAdapterPosition
|
||||
profilesAdapter.remove(index)
|
||||
undoManager.remove(index, viewHolder.asInstanceOf[ProfileViewHolder].item)
|
||||
}
|
||||
def onMove(recyclerView: RecyclerView, viewHolder: ViewHolder, target: ViewHolder) = {
|
||||
def onMove(recyclerView: RecyclerView, viewHolder: ViewHolder, target: ViewHolder): Boolean = {
|
||||
profilesAdapter.move(viewHolder.getAdapterPosition, target.getAdapterPosition)
|
||||
true
|
||||
}
|
||||
}).attachToRecyclerView(profilesList)
|
||||
|
||||
attachService(new IShadowsocksServiceCallback.Stub {
|
||||
def stateChanged(state: Int, profileName: String, msg: String) = () // ignore
|
||||
def trafficUpdated(txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long) =
|
||||
def stateChanged(state: Int, profileName: String, msg: String): Unit = () // ignore
|
||||
def trafficUpdated(txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long): Unit =
|
||||
if (selectedItem != null) selectedItem.updateText(txTotal, rxTotal)
|
||||
})
|
||||
|
||||
if (app.settings.getBoolean(Key.profileTip, true)) {
|
||||
app.editor.putBoolean(Key.profileTip, false).apply
|
||||
app.editor.putBoolean(Key.profileTip, false).apply()
|
||||
new AlertDialog.Builder(this).setTitle(R.string.profile_manager_dialog)
|
||||
.setMessage(R.string.profile_manager_dialog_content).setPositiveButton(R.string.gotcha, null).create.show
|
||||
.setMessage(R.string.profile_manager_dialog_content).setPositiveButton(R.string.gotcha, null).create().show()
|
||||
}
|
||||
|
||||
val intent = getIntent
|
||||
@@ -311,7 +310,7 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic
|
||||
val profile = app.profileManager.createProfile()
|
||||
app.profileManager.updateProfile(profile)
|
||||
app.switchProfile(profile.id)
|
||||
finish
|
||||
finish()
|
||||
case R.id.fab_qrcode_add =>
|
||||
menu.toggle(false)
|
||||
val intent = new Intent(this, classOf[ScannerActivity])
|
||||
@@ -331,18 +330,18 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic
|
||||
} else {
|
||||
dialog.setMessage(getString(R.string.add_profile_nfc_hint))
|
||||
}
|
||||
dialog.show
|
||||
dialog.show()
|
||||
case R.id.fab_import_add =>
|
||||
menu.toggle(true)
|
||||
if (clipboard.hasPrimaryClip) {
|
||||
val profiles = Parser.findAll(clipboard.getPrimaryClip.getItemAt(0).getText)
|
||||
if (profiles.nonEmpty) {
|
||||
profiles.foreach(app.profileManager.createProfile)
|
||||
Toast.makeText(this, R.string.action_import_msg, Toast.LENGTH_SHORT).show
|
||||
Toast.makeText(this, R.string.action_import_msg, Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
}
|
||||
Toast.makeText(this, R.string.action_import_err, Toast.LENGTH_SHORT).show
|
||||
Toast.makeText(this, R.string.action_import_err, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -398,11 +397,11 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic
|
||||
unregisterCallback
|
||||
}
|
||||
|
||||
override def onDestroy {
|
||||
override def onDestroy() {
|
||||
detachService()
|
||||
undoManager.flush
|
||||
undoManager.flush()
|
||||
app.profileManager.setProfileAddedListener(null)
|
||||
super.onDestroy
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override def onBackPressed() {
|
||||
@@ -417,8 +416,8 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic
|
||||
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
|
||||
case _ => Toast.makeText(this, R.string.action_export_err, Toast.LENGTH_SHORT).show
|
||||
Toast.makeText(this, R.string.action_export_msg, Toast.LENGTH_SHORT).show()
|
||||
case _ => Toast.makeText(this, R.string.action_export_err, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
true
|
||||
case _ => false
|
||||
|
||||
@@ -20,8 +20,7 @@
|
||||
|
||||
package com.github.shadowsocks
|
||||
|
||||
import android.app.{Activity, TaskStackBuilder}
|
||||
import android.content.Intent
|
||||
import android.app.TaskStackBuilder
|
||||
import android.content.pm.{PackageManager, ShortcutManager}
|
||||
import android.os.{Build, Bundle}
|
||||
import android.support.v4.app.ActivityCompat
|
||||
@@ -30,9 +29,9 @@ import android.support.v7.app.AppCompatActivity
|
||||
import android.support.v7.widget.Toolbar
|
||||
import android.text.TextUtils
|
||||
import android.widget.Toast
|
||||
import com.google.zxing.Result
|
||||
import com.github.shadowsocks.ShadowsocksApplication.app
|
||||
import com.github.shadowsocks.utils.Parser
|
||||
import com.google.zxing.Result
|
||||
import me.dm7.barcodescanner.zxing.ZXingScannerView
|
||||
|
||||
object ScannerActivity {
|
||||
@@ -95,7 +94,7 @@ class ScannerActivity extends AppCompatActivity with ZXingScannerView.ResultHand
|
||||
scannerView.stopCamera() // Stop camera on pause
|
||||
}
|
||||
|
||||
override def handleResult(rawResult: Result) = {
|
||||
override def handleResult(rawResult: Result) {
|
||||
val uri = rawResult.getText
|
||||
if (!TextUtils.isEmpty(uri))
|
||||
Parser.findAll(uri).foreach(app.profileManager.createProfile)
|
||||
|
||||
@@ -35,34 +35,34 @@ trait ServiceBoundContext extends Context with IBinder.DeathRecipient {
|
||||
binder = service
|
||||
service.linkToDeath(ServiceBoundContext.this, 0)
|
||||
bgService = IShadowsocksService.Stub.asInterface(service)
|
||||
registerCallback
|
||||
registerCallback()
|
||||
ServiceBoundContext.this.onServiceConnected()
|
||||
}
|
||||
override def onServiceDisconnected(name: ComponentName) {
|
||||
unregisterCallback
|
||||
unregisterCallback()
|
||||
ServiceBoundContext.this.onServiceDisconnected()
|
||||
bgService = null
|
||||
binder = null
|
||||
}
|
||||
}
|
||||
|
||||
protected def registerCallback = if (bgService != null && callback != null && !callbackRegistered) try {
|
||||
protected def registerCallback(): Unit = if (bgService != null && callback != null && !callbackRegistered) try {
|
||||
bgService.registerCallback(callback)
|
||||
callbackRegistered = true
|
||||
} catch {
|
||||
case ignored: RemoteException => // Nothing
|
||||
case _: RemoteException => // Nothing
|
||||
}
|
||||
|
||||
protected def unregisterCallback = {
|
||||
protected def unregisterCallback() {
|
||||
if (bgService != null && callback != null && callbackRegistered) try bgService.unregisterCallback(callback) catch {
|
||||
case ignored: RemoteException =>
|
||||
case _: RemoteException =>
|
||||
}
|
||||
callbackRegistered = false
|
||||
}
|
||||
|
||||
def onServiceConnected() = ()
|
||||
def onServiceDisconnected() = ()
|
||||
override def binderDied = ()
|
||||
def onServiceConnected(): Unit = ()
|
||||
def onServiceDisconnected(): Unit = ()
|
||||
override def binderDied(): Unit = ()
|
||||
|
||||
private var callback: IShadowsocksServiceCallback.Stub = _
|
||||
private var connection: ShadowsocksServiceConnection = _
|
||||
@@ -86,7 +86,7 @@ trait ServiceBoundContext extends Context with IBinder.DeathRecipient {
|
||||
}
|
||||
|
||||
def detachService() {
|
||||
unregisterCallback
|
||||
unregisterCallback()
|
||||
callback = null
|
||||
if (connection != null) {
|
||||
try unbindService(connection) catch {
|
||||
|
||||
@@ -123,7 +123,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
|
||||
getString(R.string.vpn_error).formatLocal(Locale.ENGLISH, m), Snackbar.LENGTH_LONG)
|
||||
if (m == getString(R.string.nat_no_root)) snackbar.setAction(R.string.switch_to_vpn,
|
||||
(_ => preferences.natSwitch.setChecked(false)): View.OnClickListener)
|
||||
snackbar.show
|
||||
snackbar.show()
|
||||
Log.e(TAG, "Error to start VPN service: " + m)
|
||||
}
|
||||
preferences.setEnabled(true)
|
||||
@@ -151,7 +151,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
|
||||
rxRateText.setText(TrafficMonitor.formatTraffic(rxRate) + "/s")
|
||||
}
|
||||
|
||||
def attachService: Unit = attachService(callback)
|
||||
def attachServiceCallback(): Unit = attachService(callback)
|
||||
|
||||
override def onServiceConnected() {
|
||||
// Update the UI
|
||||
@@ -160,7 +160,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
|
||||
if (Build.VERSION.SDK_INT >= 21 && app.isNatEnabled) {
|
||||
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
|
||||
snackbar.show()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,10 +168,10 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
|
||||
if (fab != null) fab.setEnabled(false)
|
||||
}
|
||||
|
||||
override def binderDied {
|
||||
override def binderDied() {
|
||||
detachService()
|
||||
app.crashRecovery()
|
||||
attachService
|
||||
attachServiceCallback()
|
||||
}
|
||||
|
||||
private var testCount: Int = _
|
||||
@@ -243,7 +243,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
|
||||
title.setOnClickListener(_ => startActivity(new Intent(this, classOf[ProfileManagerActivity])))
|
||||
val typedArray = obtainStyledAttributes(Array(R.attr.selectableItemBackgroundBorderless))
|
||||
title.setBackgroundResource(typedArray.getResourceId(0, 0))
|
||||
typedArray.recycle
|
||||
typedArray.recycle()
|
||||
val tf = Typefaces.get(this, "fonts/Iceland.ttf")
|
||||
if (tf != null) title.setTypeface(tf)
|
||||
title.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_arrow_drop_down, 0)
|
||||
@@ -287,7 +287,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
|
||||
synchronized(if (testCount == id && 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
|
||||
Snackbar.make(findViewById(android.R.id.content), result, Snackbar.LENGTH_LONG).show()
|
||||
}))
|
||||
}
|
||||
}
|
||||
@@ -301,12 +301,12 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
|
||||
else changeSwitch(checked = false))
|
||||
fab.setOnLongClickListener((v: View) => {
|
||||
Utils.positionToast(Toast.makeText(this, if (serviceStarted) R.string.stop else R.string.connect,
|
||||
Toast.LENGTH_SHORT), fab, getWindow, 0, Utils.dpToPx(this, 8)).show
|
||||
Toast.LENGTH_SHORT), fab, getWindow, 0, Utils.dpToPx(this, 8)).show()
|
||||
true
|
||||
})
|
||||
updateTraffic(0, 0, 0, 0)
|
||||
|
||||
handler.post(() => attachService)
|
||||
handler.post(attachServiceCallback)
|
||||
}
|
||||
|
||||
private def hideCircle() {
|
||||
@@ -412,11 +412,11 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
|
||||
|
||||
override def onStart() {
|
||||
super.onStart()
|
||||
registerCallback
|
||||
registerCallback()
|
||||
}
|
||||
override def onStop() {
|
||||
super.onStop()
|
||||
unregisterCallback
|
||||
unregisterCallback()
|
||||
clearDialog()
|
||||
}
|
||||
|
||||
@@ -436,7 +436,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
|
||||
}
|
||||
}
|
||||
|
||||
override def onActivityResult(requestCode: Int, resultCode: Int, data: Intent) = resultCode match {
|
||||
override def onActivityResult(requestCode: Int, resultCode: Int, data: Intent): Unit = resultCode match {
|
||||
case Activity.RESULT_OK =>
|
||||
serviceLoad()
|
||||
case _ =>
|
||||
|
||||
@@ -27,17 +27,18 @@ import java.util.concurrent.TimeUnit
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
import android.content.SharedPreferences
|
||||
import android.content.res.Configuration
|
||||
import android.os.{Build, LocaleList}
|
||||
import android.preference.PreferenceManager
|
||||
import android.support.v7.app.AppCompatDelegate
|
||||
import android.util.Log
|
||||
import com.evernote.android.job.JobManager
|
||||
import com.github.shadowsocks.database.{DBHelper, ProfileManager}
|
||||
import com.github.shadowsocks.database.{DBHelper, Profile, ProfileManager}
|
||||
import com.github.shadowsocks.job.DonaldTrump
|
||||
import com.github.shadowsocks.utils.CloseUtils._
|
||||
import com.github.shadowsocks.utils._
|
||||
import com.google.android.gms.analytics.{GoogleAnalytics, HitBuilders, StandardExceptionParser}
|
||||
import com.google.android.gms.analytics.{GoogleAnalytics, HitBuilders, StandardExceptionParser, Tracker}
|
||||
import com.google.android.gms.common.api.ResultCallback
|
||||
import com.google.android.gms.tagmanager.{ContainerHolder, TagManager}
|
||||
import com.j256.ormlite.logger.LocalLog
|
||||
@@ -64,29 +65,29 @@ class ShadowsocksApplication extends Application {
|
||||
|
||||
final val SIG_FUNC = "getSignature"
|
||||
var containerHolder: ContainerHolder = _
|
||||
lazy val tracker = GoogleAnalytics.getInstance(this).newTracker(R.xml.tracker)
|
||||
lazy val settings = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
lazy val editor = settings.edit
|
||||
lazy val tracker: Tracker = GoogleAnalytics.getInstance(this).newTracker(R.xml.tracker)
|
||||
lazy val settings: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
lazy val editor: SharedPreferences.Editor = settings.edit
|
||||
lazy val profileManager = new ProfileManager(new DBHelper(this))
|
||||
|
||||
def isNatEnabled = settings.getBoolean(Key.isNAT, false)
|
||||
def isVpnEnabled = !isNatEnabled
|
||||
def isNatEnabled: Boolean = settings.getBoolean(Key.isNAT, false)
|
||||
def isVpnEnabled: Boolean = !isNatEnabled
|
||||
|
||||
// send event
|
||||
def track(category: String, action: String) = tracker.send(new HitBuilders.EventBuilder()
|
||||
def track(category: String, action: String): Unit = tracker.send(new HitBuilders.EventBuilder()
|
||||
.setAction(action)
|
||||
.setLabel(BuildConfig.VERSION_NAME)
|
||||
.build())
|
||||
def track(t: Throwable) = tracker.send(new HitBuilders.ExceptionBuilder()
|
||||
def track(t: Throwable): Unit = tracker.send(new HitBuilders.ExceptionBuilder()
|
||||
.setDescription(new StandardExceptionParser(this, null).getDescription(Thread.currentThread.getName, t))
|
||||
.setFatal(false)
|
||||
.build())
|
||||
|
||||
def profileId = settings.getInt(Key.id, -1)
|
||||
def profileId(i: Int) = editor.putInt(Key.id, i).apply
|
||||
def currentProfile = profileManager.getProfile(profileId)
|
||||
def profileId: Int = settings.getInt(Key.id, -1)
|
||||
def profileId(i: Int): Unit = editor.putInt(Key.id, i).apply()
|
||||
def currentProfile: Option[Profile] = profileManager.getProfile(profileId)
|
||||
|
||||
def switchProfile(id: Int) = {
|
||||
def switchProfile(id: Int): Profile = {
|
||||
profileId(id)
|
||||
profileManager.getProfile(id) getOrElse profileManager.createProfile()
|
||||
}
|
||||
@@ -128,9 +129,11 @@ class ShadowsocksApplication extends Application {
|
||||
res.updateConfiguration(newConfig, res.getDisplayMetrics)
|
||||
}
|
||||
} else {
|
||||
//noinspection ScalaDeprecation
|
||||
val newLocale = checkChineseLocale(config.locale)
|
||||
if (newLocale != null) {
|
||||
val newConfig = new Configuration(config)
|
||||
//noinspection ScalaDeprecation
|
||||
newConfig.locale = newLocale
|
||||
val res = getResources
|
||||
res.updateConfiguration(newConfig, res.getDisplayMetrics)
|
||||
@@ -171,7 +174,7 @@ class ShadowsocksApplication extends Application {
|
||||
TcpFastOpen.enabled(settings.getBoolean(Key.tfo, TcpFastOpen.sendEnabled))
|
||||
}
|
||||
|
||||
def refreshContainerHolder {
|
||||
def refreshContainerHolder() {
|
||||
val holder = app.containerHolder
|
||||
if (holder != null) holder.refresh()
|
||||
}
|
||||
@@ -215,5 +218,5 @@ class ShadowsocksApplication extends Application {
|
||||
editor.putInt(Key.currentVersionCode, BuildConfig.VERSION_CODE).apply()
|
||||
}
|
||||
|
||||
def updateAssets() = if (settings.getInt(Key.currentVersionCode, -1) != BuildConfig.VERSION_CODE) copyAssets()
|
||||
def updateAssets(): Unit = if (settings.getInt(Key.currentVersionCode, -1) != BuildConfig.VERSION_CODE) copyAssets()
|
||||
}
|
||||
|
||||
@@ -40,11 +40,11 @@ class ShadowsocksNatService extends BaseService {
|
||||
|
||||
val TAG = "ShadowsocksNatService"
|
||||
|
||||
val CMD_IPTABLES_DNAT_ADD_SOCKS = "iptables -t nat -A OUTPUT -p tcp " +
|
||||
"-j DNAT --to-destination 127.0.0.1:8123"
|
||||
val CMD_IPTABLES_DNAT_ADD_SOCKS =
|
||||
"iptables -t nat -A OUTPUT -p tcp -j DNAT --to-destination 127.0.0.1:8123"
|
||||
|
||||
private var notification: ShadowsocksNotification = _
|
||||
val myUid = android.os.Process.myUid()
|
||||
val myUid: Int = android.os.Process.myUid()
|
||||
|
||||
var sslocalProcess: GuardedProcess = _
|
||||
var sstunnelProcess: GuardedProcess = _
|
||||
@@ -169,20 +169,17 @@ class ShadowsocksNatService extends BaseService {
|
||||
val reject = if (profile.ipv6) "224.0.0.0/3" else "224.0.0.0/3, ::/0"
|
||||
|
||||
val conf = profile.route match {
|
||||
case Route.BYPASS_CHN | Route.BYPASS_LAN_CHN | Route.GFWLIST => {
|
||||
case Route.BYPASS_CHN | Route.BYPASS_LAN_CHN | Route.GFWLIST =>
|
||||
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, "", getApplicationInfo.dataDir,
|
||||
"127.0.0.1", profile.localPort + 53, "114.114.114.114, 223.5.5.5, 1.2.4.8",
|
||||
getBlackList, reject, profile.localPort + 63, reject)
|
||||
}
|
||||
case Route.CHINALIST => {
|
||||
case Route.CHINALIST =>
|
||||
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, "", getApplicationInfo.dataDir,
|
||||
"127.0.0.1", profile.localPort + 53, "8.8.8.8, 8.8.4.4, 208.67.222.222",
|
||||
"", reject, profile.localPort + 63, reject)
|
||||
}
|
||||
case _ => {
|
||||
case _ =>
|
||||
ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, "", getApplicationInfo.dataDir,
|
||||
"127.0.0.1", profile.localPort + 53, profile.localPort + 63, reject)
|
||||
}
|
||||
}
|
||||
|
||||
Utils.printToFile(new File(getApplicationInfo.dataDir + "/pdnsd-nat.conf"))(p => {
|
||||
@@ -254,7 +251,7 @@ class ShadowsocksNatService extends BaseService {
|
||||
su.addCommand("iptables -t nat -F OUTPUT")
|
||||
}
|
||||
|
||||
def setupIptables() = {
|
||||
def setupIptables() {
|
||||
val init_sb = new ArrayBuffer[String]
|
||||
val http_sb = new ArrayBuffer[String]
|
||||
|
||||
@@ -291,14 +288,14 @@ class ShadowsocksNatService extends BaseService {
|
||||
su.addCommand((init_sb ++ http_sb).toArray)
|
||||
}
|
||||
|
||||
override def startRunner(profile: Profile) = if (su == null)
|
||||
override def startRunner(profile: Profile): Unit = if (su == null)
|
||||
su = new Shell.Builder().useSU().setWantSTDERR(true).setWatchdogTimeout(10).open((_, exitCode, _) =>
|
||||
if (exitCode == 0) super.startRunner(profile) else {
|
||||
if (su != null) {
|
||||
su.close()
|
||||
su = null
|
||||
}
|
||||
super.stopRunner(true, getString(R.string.nat_no_root))
|
||||
super.stopRunner(stopService = true, getString(R.string.nat_no_root))
|
||||
})
|
||||
|
||||
override def connect() {
|
||||
|
||||
@@ -39,7 +39,7 @@ class ShadowsocksNotification(private val service: BaseService, profileName: Str
|
||||
private val keyGuard = service.getSystemService(Context.KEYGUARD_SERVICE).asInstanceOf[KeyguardManager]
|
||||
private lazy val nm = service.getSystemService(Context.NOTIFICATION_SERVICE).asInstanceOf[NotificationManager]
|
||||
private lazy val callback = new Stub {
|
||||
override def stateChanged(state: Int, profileName: String, msg: String) = () // ignore
|
||||
override def stateChanged(state: Int, profileName: String, msg: String): Unit = () // ignore
|
||||
override def trafficUpdated(txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long) {
|
||||
val txr = TrafficMonitor.formatTraffic(txRate)
|
||||
val rxr = TrafficMonitor.formatTraffic(rxRate)
|
||||
@@ -71,8 +71,8 @@ class ShadowsocksNotification(private val service: BaseService, profileName: Str
|
||||
private lazy val style = new BigTextStyle(builder)
|
||||
private var isVisible = true
|
||||
update(if (service.getSystemService(Context.POWER_SERVICE).asInstanceOf[PowerManager].isScreenOn)
|
||||
Intent.ACTION_SCREEN_ON else Intent.ACTION_SCREEN_OFF, true)
|
||||
lockReceiver = (context: Context, intent: Intent) => update(intent.getAction)
|
||||
Intent.ACTION_SCREEN_ON else Intent.ACTION_SCREEN_OFF, forceShow = true)
|
||||
lockReceiver = (_: Context, intent: Intent) => update(intent.getAction)
|
||||
val screenFilter = new IntentFilter()
|
||||
screenFilter.addAction(Intent.ACTION_SCREEN_ON)
|
||||
screenFilter.addAction(Intent.ACTION_SCREEN_OFF)
|
||||
@@ -83,33 +83,33 @@ class ShadowsocksNotification(private val service: BaseService, profileName: Str
|
||||
if (forceShow || service.getState == State.CONNECTED) action match {
|
||||
case Intent.ACTION_SCREEN_OFF =>
|
||||
setVisible(visible && !Utils.isLollipopOrAbove, forceShow)
|
||||
unregisterCallback // unregister callback to save battery
|
||||
unregisterCallback() // unregister callback to save battery
|
||||
case Intent.ACTION_SCREEN_ON =>
|
||||
setVisible(visible && Utils.isLollipopOrAbove && !keyGuard.inKeyguardRestrictedInputMode, forceShow)
|
||||
service.binder.registerCallback(callback)
|
||||
callbackRegistered = true
|
||||
case Intent.ACTION_USER_PRESENT => setVisible(true, forceShow)
|
||||
case Intent.ACTION_USER_PRESENT => setVisible(visible = true, forceShow = forceShow)
|
||||
}
|
||||
|
||||
private def unregisterCallback = if (callbackRegistered) {
|
||||
private def unregisterCallback() = if (callbackRegistered) {
|
||||
service.binder.unregisterCallback(callback)
|
||||
callbackRegistered = false
|
||||
}
|
||||
|
||||
def setVisible(visible: Boolean, forceShow: Boolean = false) = if (isVisible != visible) {
|
||||
def setVisible(visible: Boolean, forceShow: Boolean = false): Unit = if (isVisible != visible) {
|
||||
isVisible = visible
|
||||
builder.setPriority(if (visible) NotificationCompat.PRIORITY_LOW else NotificationCompat.PRIORITY_MIN)
|
||||
show()
|
||||
} else if (forceShow) show()
|
||||
|
||||
def show() = service.startForeground(1, builder.build)
|
||||
def show(): Unit = service.startForeground(1, builder.build)
|
||||
|
||||
def destroy() {
|
||||
if (lockReceiver != null) {
|
||||
service.unregisterReceiver(lockReceiver)
|
||||
lockReceiver = null
|
||||
}
|
||||
unregisterCallback
|
||||
unregisterCallback()
|
||||
service.stopForeground(true)
|
||||
nm.cancel(1)
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ class ShadowsocksQuickSwitchActivity extends AppCompatActivity {
|
||||
{
|
||||
val typedArray = obtainStyledAttributes(Array(android.R.attr.selectableItemBackground))
|
||||
view.setBackgroundResource(typedArray.getResourceId(0, 0))
|
||||
typedArray.recycle
|
||||
typedArray.recycle()
|
||||
}
|
||||
private var item: Profile = _
|
||||
private val text = itemView.findViewById(android.R.id.text1).asInstanceOf[CheckedTextView]
|
||||
@@ -55,16 +55,16 @@ class ShadowsocksQuickSwitchActivity extends AppCompatActivity {
|
||||
def onClick(v: View) {
|
||||
app.switchProfile(item.id)
|
||||
Utils.startSsService(ShadowsocksQuickSwitchActivity.this)
|
||||
finish
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
private class ProfilesAdapter extends RecyclerView.Adapter[ProfileViewHolder] {
|
||||
val profiles = app.profileManager.getAllProfiles.getOrElse(List.empty[Profile])
|
||||
val profiles: List[Profile] = app.profileManager.getAllProfiles.getOrElse(List.empty[Profile])
|
||||
|
||||
def getItemCount = profiles.length
|
||||
def getItemCount: Int = profiles.length
|
||||
|
||||
def onBindViewHolder(vh: ProfileViewHolder, i: Int) = i match {
|
||||
def onBindViewHolder(vh: ProfileViewHolder, i: Int): Unit = i match {
|
||||
case _ => vh.bind(profiles(i))
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ import android.content.{BroadcastReceiver, Context, Intent, IntentFilter}
|
||||
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 {
|
||||
@@ -65,7 +64,7 @@ class ShadowsocksRunnerActivity extends Activity with ServiceBoundContext {
|
||||
val locked = km.inKeyguardRestrictedInputMode
|
||||
if (locked) {
|
||||
val filter = new IntentFilter(Intent.ACTION_USER_PRESENT)
|
||||
receiver = (context: Context, intent: Intent) => {
|
||||
receiver = (_: Context, intent: Intent) => {
|
||||
if (intent.getAction == Intent.ACTION_USER_PRESENT) {
|
||||
attachService()
|
||||
}
|
||||
@@ -74,7 +73,7 @@ class ShadowsocksRunnerActivity extends Activity with ServiceBoundContext {
|
||||
} else {
|
||||
attachService()
|
||||
}
|
||||
finish
|
||||
finish()
|
||||
}
|
||||
|
||||
override def onDestroy() {
|
||||
|
||||
@@ -23,8 +23,7 @@ package com.github.shadowsocks
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import android.net.VpnService
|
||||
import android.os.{IBinder, Handler}
|
||||
import com.github.shadowsocks.utils.ConfigUtils
|
||||
import android.os.{Handler, IBinder}
|
||||
import com.github.shadowsocks.ShadowsocksApplication.app
|
||||
|
||||
class ShadowsocksRunnerService extends Service with ServiceBoundContext {
|
||||
@@ -44,7 +43,7 @@ class ShadowsocksRunnerService extends Service with ServiceBoundContext {
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
def startBackgroundService() = bgService.useSync(app.profileId)
|
||||
def startBackgroundService(): Unit = bgService.useSync(app.profileId)
|
||||
|
||||
override def onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
@@ -97,7 +97,7 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan
|
||||
import ShadowsocksSettings._
|
||||
|
||||
private def activity = getActivity.asInstanceOf[Shadowsocks]
|
||||
lazy val natSwitch = findPreference(Key.isNAT).asInstanceOf[SwitchPreference]
|
||||
lazy val natSwitch: SwitchPreference = findPreference(Key.isNAT).asInstanceOf[SwitchPreference]
|
||||
|
||||
private var isProxyApps: SwitchPreference = _
|
||||
|
||||
@@ -182,7 +182,7 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan
|
||||
})
|
||||
if (getPreferenceManager.getSharedPreferences.getBoolean(Key.isAutoConnect, false)) {
|
||||
BootReceiver.setEnabled(activity, true)
|
||||
getPreferenceManager.getSharedPreferences.edit.remove(Key.isAutoConnect).apply
|
||||
getPreferenceManager.getSharedPreferences.edit.remove(Key.isAutoConnect).apply()
|
||||
}
|
||||
switch.setChecked(BootReceiver.getEnabled(activity))
|
||||
|
||||
@@ -200,13 +200,13 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan
|
||||
tfo.setSummary(getString(R.string.tcp_fastopen_summary_unsupported, java.lang.System.getProperty("os.version")))
|
||||
}
|
||||
|
||||
findPreference("recovery").setOnPreferenceClickListener((preference: Preference) => {
|
||||
findPreference("recovery").setOnPreferenceClickListener(_ => {
|
||||
app.track(TAG, "reset")
|
||||
activity.recovery()
|
||||
true
|
||||
})
|
||||
|
||||
findPreference("about").setOnPreferenceClickListener((preference: Preference) => {
|
||||
findPreference("about").setOnPreferenceClickListener(_ => {
|
||||
app.track(TAG, "about")
|
||||
val web = new WebView(activity)
|
||||
web.loadUrl("file:///android_asset/pages/about.html")
|
||||
@@ -231,7 +231,7 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan
|
||||
})
|
||||
}
|
||||
|
||||
override def onDisplayPreferenceDialog(preference: Preference) = preference.getKey match {
|
||||
override def onDisplayPreferenceDialog(preference: Preference): Unit = preference.getKey match {
|
||||
case Key.kcpcli => displayPreferenceDialog(Key.kcpcli, new KcpCliPreferenceDialogFragment())
|
||||
case _ => super.onDisplayPreferenceDialog(preference)
|
||||
}
|
||||
@@ -253,16 +253,16 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan
|
||||
isProxyApps.setChecked(profile.proxyApps)
|
||||
}
|
||||
|
||||
override def onDestroy {
|
||||
override def onDestroy() {
|
||||
super.onDestroy()
|
||||
app.settings.unregisterOnSharedPreferenceChangeListener(this)
|
||||
}
|
||||
|
||||
def onSharedPreferenceChanged(pref: SharedPreferences, key: String) = key match {
|
||||
def onSharedPreferenceChanged(pref: SharedPreferences, key: String): Unit = key match {
|
||||
case Key.isNAT =>
|
||||
activity.handler.post(() => {
|
||||
activity.detachService
|
||||
activity.attachService
|
||||
activity.detachService()
|
||||
activity.attachServiceCallback()
|
||||
})
|
||||
case _ =>
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ final class ShadowsocksTileService extends TileService with ServiceBoundContext
|
||||
private lazy val iconBusy = Icon.createWithResource(this, R.drawable.ic_start_busy)
|
||||
private lazy val iconConnected = Icon.createWithResource(this, R.drawable.ic_start_connected)
|
||||
private lazy val callback = new IShadowsocksServiceCallback.Stub {
|
||||
def trafficUpdated(txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long) = ()
|
||||
def trafficUpdated(txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long): Unit = ()
|
||||
def stateChanged(state: Int, profileName: String, msg: String) {
|
||||
val tile = getQsTile
|
||||
if (tile != null) {
|
||||
@@ -54,23 +54,23 @@ final class ShadowsocksTileService extends TileService with ServiceBoundContext
|
||||
tile.setLabel(getString(R.string.app_name))
|
||||
tile.setState(Tile.STATE_UNAVAILABLE)
|
||||
}
|
||||
tile.updateTile
|
||||
tile.updateTile()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override def onServiceConnected() = callback.stateChanged(bgService.getState, bgService.getProfileName, null)
|
||||
override def onServiceConnected(): Unit = callback.stateChanged(bgService.getState, bgService.getProfileName, null)
|
||||
|
||||
override def onStartListening {
|
||||
super.onStartListening
|
||||
override def onStartListening() {
|
||||
super.onStartListening()
|
||||
attachService(callback)
|
||||
}
|
||||
override def onStopListening {
|
||||
super.onStopListening
|
||||
detachService // just in case the user switches to NAT mode, also saves battery
|
||||
override def onStopListening() {
|
||||
super.onStopListening()
|
||||
detachService() // just in case the user switches to NAT mode, also saves battery
|
||||
}
|
||||
|
||||
override def onClick() = if (isLocked) unlockAndRun(toggle) else toggle()
|
||||
override def onClick(): Unit = if (isLocked) unlockAndRun(toggle) else toggle()
|
||||
|
||||
private def toggle() = if (bgService != null) bgService.getState match {
|
||||
case State.STOPPED => Utils.startSsService(this)
|
||||
|
||||
@@ -61,7 +61,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
}
|
||||
|
||||
override def onRevoke() {
|
||||
stopRunner(true)
|
||||
stopRunner(stopService = true)
|
||||
}
|
||||
|
||||
override def stopRunner(stopService: Boolean, msg: String = null) {
|
||||
@@ -120,14 +120,14 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
val i = new Intent(this, classOf[ShadowsocksRunnerActivity])
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
startActivity(i)
|
||||
stopRunner(true)
|
||||
stopRunner(stopService = true)
|
||||
return
|
||||
}
|
||||
|
||||
super.startRunner(profile)
|
||||
}
|
||||
|
||||
override def connect() = {
|
||||
override def connect() {
|
||||
super.connect()
|
||||
|
||||
vpnThread = new ShadowsocksVpnThread(this)
|
||||
@@ -253,7 +253,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
sslocalProcess = new GuardedProcess(cmd).start()
|
||||
}
|
||||
|
||||
def startDnsTunnel() = {
|
||||
def startDnsTunnel() {
|
||||
val conf = if (profile.kcp) {
|
||||
ConfigUtils
|
||||
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, "127.0.0.1", profile.localPort + 90, profile.localPort + 63,
|
||||
@@ -291,20 +291,17 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
val reject = if (profile.ipv6) "224.0.0.0/3" else "224.0.0.0/3, ::/0"
|
||||
val protect = "protect = \"" + protectPath +"\";"
|
||||
val conf = profile.route match {
|
||||
case Route.BYPASS_CHN | Route.BYPASS_LAN_CHN | Route.GFWLIST => {
|
||||
case Route.BYPASS_CHN | Route.BYPASS_LAN_CHN | Route.GFWLIST =>
|
||||
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, protect, getApplicationInfo.dataDir,
|
||||
"0.0.0.0", profile.localPort + 53, "114.114.114.114, 223.5.5.5, 1.2.4.8",
|
||||
getBlackList, reject, profile.localPort + 63, reject)
|
||||
}
|
||||
case Route.CHINALIST => {
|
||||
case Route.CHINALIST =>
|
||||
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, protect, getApplicationInfo.dataDir,
|
||||
"0.0.0.0", profile.localPort + 53, "8.8.8.8, 8.8.4.4, 208.67.222.222",
|
||||
"", reject, profile.localPort + 63, reject)
|
||||
}
|
||||
case _ => {
|
||||
case _ =>
|
||||
ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, protect, getApplicationInfo.dataDir,
|
||||
"0.0.0.0", profile.localPort + 53, profile.localPort + 63, reject)
|
||||
}
|
||||
}
|
||||
Utils.printToFile(new File(getApplicationInfo.dataDir + "/pdnsd-vpn.conf"))(p => {
|
||||
p.println(conf)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
package com.github.shadowsocks
|
||||
|
||||
import java.io.{File, FileDescriptor, IOException}
|
||||
import java.lang.reflect.Method
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
import android.net.{LocalServerSocket, LocalSocket, LocalSocketAddress}
|
||||
@@ -28,14 +29,14 @@ import android.util.Log
|
||||
import com.github.shadowsocks.ShadowsocksApplication.app
|
||||
|
||||
object ShadowsocksVpnThread {
|
||||
val getInt = classOf[FileDescriptor].getDeclaredMethod("getInt$")
|
||||
val getInt: Method = classOf[FileDescriptor].getDeclaredMethod("getInt$")
|
||||
}
|
||||
|
||||
class ShadowsocksVpnThread(vpnService: ShadowsocksVpnService) extends Thread {
|
||||
import ShadowsocksVpnThread._
|
||||
|
||||
val TAG = "ShadowsocksVpnService"
|
||||
lazy val PATH = vpnService.getApplicationInfo.dataDir + "/protect_path"
|
||||
lazy val PATH: String = vpnService.getApplicationInfo.dataDir + "/protect_path"
|
||||
|
||||
@volatile var isRunning: Boolean = true
|
||||
@volatile var serverSocket: LocalServerSocket = _
|
||||
|
||||
@@ -39,13 +39,13 @@ class TaskerActivity extends AppCompatActivity {
|
||||
{
|
||||
val typedArray = obtainStyledAttributes(Array(android.R.attr.selectableItemBackground))
|
||||
view.setBackgroundResource(typedArray.getResourceId(0, 0))
|
||||
typedArray.recycle
|
||||
typedArray.recycle()
|
||||
}
|
||||
private var item: Profile = _
|
||||
private val text = itemView.findViewById(android.R.id.text1).asInstanceOf[CheckedTextView]
|
||||
itemView.setOnClickListener(this)
|
||||
|
||||
def bindDefault {
|
||||
def bindDefault() {
|
||||
item = null
|
||||
text.setText(R.string.profile_default)
|
||||
text.setChecked(taskerOption.profileId < 0)
|
||||
@@ -60,15 +60,15 @@ class TaskerActivity extends AppCompatActivity {
|
||||
taskerOption.switchOn = switch.isChecked
|
||||
taskerOption.profileId = if (item == null) -1 else item.id
|
||||
setResult(Activity.RESULT_OK, taskerOption.toIntent(TaskerActivity.this))
|
||||
finish
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
private class ProfilesAdapter extends RecyclerView.Adapter[ProfileViewHolder] {
|
||||
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
|
||||
val profiles: List[Profile] = app.profileManager.getAllProfiles.getOrElse(List.empty[Profile])
|
||||
def getItemCount: Int = 1 + profiles.length
|
||||
def onBindViewHolder(vh: ProfileViewHolder, i: Int): Unit = i match {
|
||||
case 0 => vh.bindDefault()
|
||||
case _ => vh.bind(profiles(i - 1))
|
||||
}
|
||||
private val name = "select_dialog_singlechoice_" + (if (Build.VERSION.SDK_INT >= 21) "material" else "holo")
|
||||
|
||||
@@ -30,11 +30,9 @@ import com.github.shadowsocks.ShadowsocksApplication.app
|
||||
class TaskerReceiver extends BroadcastReceiver {
|
||||
override def onReceive(context: Context, intent: Intent) {
|
||||
val settings = TaskerSettings.fromIntent(intent)
|
||||
val switched = app.profileManager.getProfile(settings.profileId) match {
|
||||
case Some(p) =>
|
||||
app.switchProfile(settings.profileId)
|
||||
true
|
||||
case _ => false
|
||||
app.profileManager.getProfile(settings.profileId) match {
|
||||
case Some(_) => app.switchProfile(settings.profileId)
|
||||
case _ =>
|
||||
}
|
||||
if (settings.switchOn) Utils.startSsService(context) else Utils.stopSsService(context)
|
||||
}
|
||||
|
||||
@@ -36,9 +36,9 @@ object DBHelper {
|
||||
final val PROFILE = "profile.db"
|
||||
private var apps: mutable.Buffer[ApplicationInfo] = _
|
||||
|
||||
def isAllDigits(x: String) = !x.isEmpty && (x forall Character.isDigit)
|
||||
def isAllDigits(x: String): Boolean = !x.isEmpty && (x forall Character.isDigit)
|
||||
|
||||
def updateProxiedApps(context: Context, old: String) = {
|
||||
def updateProxiedApps(context: Context, old: String): String = {
|
||||
synchronized(if (apps == null) apps = context.getPackageManager.getInstalledApplications(0).asScala)
|
||||
val uidSet = old.split('|').filter(isAllDigits).map(_.toInt).toSet
|
||||
apps.filter(ai => uidSet.contains(ai.uid)).map(_.packageName).mkString("\n")
|
||||
|
||||
@@ -95,9 +95,9 @@ class Profile {
|
||||
@DatabaseField
|
||||
var kcpcli: String = "--crypt none --mode normal --mtu 1200 --nocomp --dscp 46 --parityshard 0"
|
||||
|
||||
override def toString = "ss://" + Base64.encodeToString("%s%s:%s@%s:%d".formatLocal(Locale.ENGLISH,
|
||||
override def toString: String = "ss://" + Base64.encodeToString("%s%s:%s@%s:%d".formatLocal(Locale.ENGLISH,
|
||||
method, if (auth) "-auth" else "", password, host, remotePort).getBytes, Base64.NO_PADDING | Base64.NO_WRAP) +
|
||||
'#' + URLEncoder.encode(name, "utf-8")
|
||||
|
||||
def isMethodUnsafe = "table".equalsIgnoreCase(method) || "rc4".equalsIgnoreCase(method)
|
||||
def isMethodUnsafe: Boolean = "table".equalsIgnoreCase(method) || "rc4".equalsIgnoreCase(method)
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ class ProfileManager(dbHelper: DBHelper) {
|
||||
import ProfileManager._
|
||||
|
||||
var profileAddedListener: Profile => Any = _
|
||||
def setProfileAddedListener(listener: Profile => Any) = this.profileAddedListener = listener
|
||||
def setProfileAddedListener(listener: Profile => Any): Unit = this.profileAddedListener = listener
|
||||
|
||||
def createProfile(p: Profile = null): Profile = {
|
||||
val profile = if (p == null) new Profile else p
|
||||
@@ -99,7 +99,7 @@ class ProfileManager(dbHelper: DBHelper) {
|
||||
}
|
||||
}
|
||||
|
||||
def getFirstProfile = {
|
||||
def getFirstProfile: Option[Profile] = {
|
||||
try {
|
||||
val result = dbHelper.profileDao.query(dbHelper.profileDao.queryBuilder.limit(1L).prepare)
|
||||
if (result.size == 1) Option(result.get(0)) else None
|
||||
|
||||
@@ -36,7 +36,7 @@ import com.github.shadowsocks.utils.IOUtils
|
||||
object AclSyncJob {
|
||||
final val TAG = "AclSyncJob"
|
||||
|
||||
def schedule(route: String) = new JobRequest.Builder(AclSyncJob.TAG + ':' + route)
|
||||
def schedule(route: String): Int = new JobRequest.Builder(AclSyncJob.TAG + ':' + route)
|
||||
.setExecutionWindow(1, TimeUnit.DAYS.toMillis(28))
|
||||
.setRequirementsEnforced(true)
|
||||
.setRequiredNetworkType(JobRequest.NetworkType.UNMETERED)
|
||||
|
||||
@@ -32,7 +32,7 @@ import com.evernote.android.job.JobCreator
|
||||
* @author !Mygod
|
||||
*/
|
||||
object DonaldTrump extends JobCreator {
|
||||
def create(tag: String) = {
|
||||
def create(tag: String): AclSyncJob = {
|
||||
val parts = tag.split(":")
|
||||
parts(0) match {
|
||||
case AclSyncJob.TAG => new AclSyncJob(parts(1))
|
||||
|
||||
@@ -35,9 +35,9 @@ object CloseUtils {
|
||||
block(a.get)
|
||||
} finally if (a.nonEmpty) try {
|
||||
val v = a.get
|
||||
if (v ne null) v.close
|
||||
if (v ne null) v.close()
|
||||
} catch {
|
||||
case ignore: Exception =>
|
||||
case _: Exception =>
|
||||
}
|
||||
}
|
||||
def autoDisconnect[A <: Disconnectable, B](x: => A)(block: A => B): B = {
|
||||
@@ -47,9 +47,9 @@ object CloseUtils {
|
||||
block(a.get)
|
||||
} finally if (a.nonEmpty) try {
|
||||
val v = a.get
|
||||
if (v ne null) v.disconnect
|
||||
if (v ne null) v.disconnect()
|
||||
} catch {
|
||||
case ignore: Exception =>
|
||||
case _: Exception =>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,5 +47,6 @@ object IOUtils {
|
||||
null
|
||||
}
|
||||
|
||||
def writeString(file: String, content: String) = autoClose(new FileWriter(file))(writer => writer.write(content))
|
||||
def writeString(file: String, content: String): Unit =
|
||||
autoClose(new FileWriter(file))(writer => writer.write(content))
|
||||
}
|
||||
|
||||
@@ -30,23 +30,23 @@ object Parser {
|
||||
private val pattern = "(?i)ss://([A-Za-z0-9+-/=_]+)(#(.+))?".r
|
||||
private val decodedPattern = "(?i)^((.+?)(-auth)??:(.*)@(.+?):(\\d+?))$".r
|
||||
|
||||
def findAll(data: CharSequence) = pattern.findAllMatchIn(if (data == null) "" else data).map(m => try
|
||||
decodedPattern.findFirstMatchIn(new String(Base64.decode(m.group(1), Base64.NO_PADDING), "UTF-8")) match {
|
||||
case Some(ss) =>
|
||||
val profile = new Profile
|
||||
profile.method = ss.group(2).toLowerCase
|
||||
if (ss.group(3) != null) profile.auth = true
|
||||
profile.password = ss.group(4)
|
||||
profile.name = ss.group(5)
|
||||
profile.host = profile.name
|
||||
profile.remotePort = ss.group(6).toInt
|
||||
if (m.group(2) != null) profile.name = URLDecoder.decode(m.group(3), "utf-8")
|
||||
profile
|
||||
case _ => null
|
||||
}
|
||||
catch {
|
||||
case ex: Exception =>
|
||||
Log.e(TAG, "parser error: " + m.source, ex)// Ignore
|
||||
null
|
||||
}).filter(_ != null)
|
||||
def findAll(data: CharSequence): Iterator[Profile] =
|
||||
pattern.findAllMatchIn(if (data == null) "" else data).map(m => try
|
||||
decodedPattern.findFirstMatchIn(new String(Base64.decode(m.group(1), Base64.NO_PADDING), "UTF-8")) match {
|
||||
case Some(ss) =>
|
||||
val profile = new Profile
|
||||
profile.method = ss.group(2).toLowerCase
|
||||
if (ss.group(3) != null) profile.auth = true
|
||||
profile.password = ss.group(4)
|
||||
profile.name = ss.group(5)
|
||||
profile.host = profile.name
|
||||
profile.remotePort = ss.group(6).toInt
|
||||
if (m.group(2) != null) profile.name = URLDecoder.decode(m.group(3), "utf-8")
|
||||
profile
|
||||
case _ => null
|
||||
} catch {
|
||||
case ex: Exception =>
|
||||
Log.e(TAG, "parser error: " + m.source, ex)// Ignore
|
||||
null
|
||||
}).filter(_ != null)
|
||||
}
|
||||
|
||||
@@ -37,10 +37,10 @@ object TaskerSettings {
|
||||
class TaskerSettings(bundle: Bundle) {
|
||||
import TaskerSettings._
|
||||
|
||||
var switchOn = bundle.getBoolean(KEY_SWITCH_ON, true)
|
||||
var profileId = bundle.getInt(KEY_PROFILE_ID, -1)
|
||||
var switchOn: Boolean = bundle.getBoolean(KEY_SWITCH_ON, true)
|
||||
var profileId: Int = bundle.getInt(KEY_PROFILE_ID, -1)
|
||||
|
||||
def toIntent(context: Context) = {
|
||||
def toIntent(context: Context): Intent = {
|
||||
val bundle = new Bundle()
|
||||
if (!switchOn) bundle.putBoolean(KEY_SWITCH_ON, false)
|
||||
if (profileId >= 0) bundle.putInt(KEY_PROFILE_ID, profileId)
|
||||
|
||||
@@ -33,7 +33,7 @@ object TcpFastOpen {
|
||||
/**
|
||||
* Is kernel version >= 3.7.1.
|
||||
*/
|
||||
lazy val supported = "^(\\d+)\\.(\\d+)\\.(\\d+)".r.findFirstMatchIn(System.getProperty("os.version")) match {
|
||||
lazy val supported: Boolean = "^(\\d+)\\.(\\d+)\\.(\\d+)".r.findFirstMatchIn(System.getProperty("os.version")) match {
|
||||
case Some(m) =>
|
||||
val kernel = m.group(1).toInt
|
||||
if (kernel < 3) false else if (kernel > 3) true else {
|
||||
@@ -43,7 +43,7 @@ object TcpFastOpen {
|
||||
case _ => false
|
||||
}
|
||||
|
||||
def sendEnabled = {
|
||||
def sendEnabled: Boolean = {
|
||||
val file = new File("/proc/sys/net/ipv4/tcp_fastopen")
|
||||
file.canRead && (Utils.readAllLines(file).toInt & 1) > 0
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ object TrafficMonitor {
|
||||
else numberFormat.format(n) + ' ' + units(i)
|
||||
}
|
||||
|
||||
def updateRate() = {
|
||||
def updateRate(): Boolean = {
|
||||
val now = System.currentTimeMillis()
|
||||
val delta = now - timestampLast
|
||||
var updated = false
|
||||
|
||||
@@ -32,7 +32,7 @@ import com.github.shadowsocks.ShadowsocksApplication.app
|
||||
class TrafficMonitorThread(context: Context) extends Thread {
|
||||
|
||||
val TAG = "TrafficMonitorThread"
|
||||
lazy val PATH = context.getApplicationInfo.dataDir + "/stat_path"
|
||||
lazy val PATH: String = context.getApplicationInfo.dataDir + "/stat_path"
|
||||
|
||||
@volatile var serverSocket: LocalServerSocket = _
|
||||
@volatile var isRunning: Boolean = true
|
||||
|
||||
@@ -66,7 +66,7 @@ object Utils {
|
||||
*/
|
||||
|
||||
// Based on: http://stackoverflow.com/a/21026866/2245107
|
||||
def positionToast(toast: Toast, view: View, window: Window, offsetX: Int = 0, offsetY: Int = 0) = {
|
||||
def positionToast(toast: Toast, view: View, window: Window, offsetX: Int = 0, offsetY: Int = 0): Toast = {
|
||||
val rect = new Rect
|
||||
window.getDecorView.getWindowVisibleDisplayFrame(rect)
|
||||
val viewLocation = new Array[Int](2)
|
||||
@@ -88,11 +88,11 @@ object Utils {
|
||||
to.setVisibility(View.VISIBLE)
|
||||
to.animate().alpha(1).setDuration(shortAnimTime)
|
||||
from.animate().alpha(0).setDuration(shortAnimTime).setListener(new AnimatorListenerAdapter {
|
||||
override def onAnimationEnd(animation: Animator) = from.setVisibility(View.GONE)
|
||||
override def onAnimationEnd(animation: Animator): Unit = from.setVisibility(View.GONE)
|
||||
})
|
||||
}
|
||||
|
||||
def readAllLines(f: File) = {
|
||||
def readAllLines(f: File): String = {
|
||||
val scanner = new Scanner(f)
|
||||
try {
|
||||
scanner.useDelimiter("\\Z")
|
||||
@@ -168,40 +168,18 @@ object Utils {
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
case e: Exception =>
|
||||
case _: Exception =>
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
def resolve(host: String): Option[String] = {
|
||||
try {
|
||||
val addr = InetAddress.getByName(host)
|
||||
Some(addr.getHostAddress)
|
||||
} catch {
|
||||
case e: UnknownHostException => None
|
||||
}
|
||||
def resolve(host: String): Option[String] = try Some(InetAddress.getByName(host).getHostAddress) catch {
|
||||
case _: UnknownHostException => None
|
||||
}
|
||||
|
||||
def resolve(host: String, enableIPv6: Boolean): Option[String] = {
|
||||
if (enableIPv6 && Utils.isIPv6Support) {
|
||||
resolve(host, Type.AAAA) match {
|
||||
case Some(addr) =>
|
||||
return Some(addr)
|
||||
case None =>
|
||||
}
|
||||
}
|
||||
resolve(host, Type.A) match {
|
||||
case Some(addr) =>
|
||||
return Some(addr)
|
||||
case None =>
|
||||
}
|
||||
resolve(host) match {
|
||||
case Some(addr) =>
|
||||
return Some(addr)
|
||||
case None =>
|
||||
}
|
||||
None
|
||||
}
|
||||
def resolve(host: String, enableIPv6: Boolean): Option[String] =
|
||||
(if (enableIPv6 && Utils.isIPv6Support) resolve(host, Type.AAAA) else None).orElse(resolve(host, Type.A))
|
||||
.orElse(resolve(host))
|
||||
|
||||
private lazy val isNumericMethod = classOf[InetAddress].getMethod("isNumeric", classOf[String])
|
||||
def isNumeric(address: String): Boolean = isNumericMethod.invoke(null, address).asInstanceOf[Boolean]
|
||||
@@ -242,5 +220,5 @@ object Utils {
|
||||
case _ =>
|
||||
}
|
||||
|
||||
def ThrowableFuture[T](f: => T) = Future(f) onComplete handleFailure
|
||||
def ThrowableFuture[T](f: => T): Unit = Future(f) onComplete handleFailure
|
||||
}
|
||||
|
||||
@@ -42,10 +42,11 @@ class FloatingActionMenuBehavior(context: Context, attrs: AttributeSet)
|
||||
private var fabTranslationYAnimator: ValueAnimator = _
|
||||
private var fabTranslationY: Float = _
|
||||
|
||||
override def layoutDependsOn(parent: CoordinatorLayout, child: FloatingActionMenu, dependency: View) =
|
||||
override def layoutDependsOn(parent: CoordinatorLayout, child: FloatingActionMenu, dependency: View): Boolean =
|
||||
dependency.isInstanceOf[SnackbarLayout]
|
||||
|
||||
override def onDependentViewChanged(parent: CoordinatorLayout, child: FloatingActionMenu, dependency: View) = {
|
||||
override def onDependentViewChanged(parent: CoordinatorLayout, child: FloatingActionMenu,
|
||||
dependency: View): Boolean = {
|
||||
dependency match {
|
||||
case _: SnackbarLayout =>
|
||||
var targetTransY = parent.getDependencies(child).asScala
|
||||
@@ -54,7 +55,7 @@ class FloatingActionMenuBehavior(context: Context, attrs: AttributeSet)
|
||||
if (targetTransY > 0) targetTransY = 0
|
||||
if (fabTranslationY != targetTransY) {
|
||||
val currentTransY = child.getTranslationY
|
||||
if (fabTranslationYAnimator != null && fabTranslationYAnimator.isRunning) fabTranslationYAnimator.cancel
|
||||
if (fabTranslationYAnimator != null && fabTranslationYAnimator.isRunning) fabTranslationYAnimator.cancel()
|
||||
if (child.isShown && Math.abs(currentTransY - targetTransY) > child.getHeight * 0.667F) {
|
||||
if (fabTranslationYAnimator == null) {
|
||||
fabTranslationYAnimator = new ValueAnimator
|
||||
@@ -63,7 +64,7 @@ class FloatingActionMenuBehavior(context: Context, attrs: AttributeSet)
|
||||
child.setTranslationY(animation.getAnimatedValue.asInstanceOf[Float]))
|
||||
}
|
||||
fabTranslationYAnimator.setFloatValues(currentTransY, targetTransY)
|
||||
fabTranslationYAnimator.start
|
||||
fabTranslationYAnimator.start()
|
||||
} else child.setTranslationY(targetTransY)
|
||||
fabTranslationY = targetTransY
|
||||
}
|
||||
@@ -74,7 +75,7 @@ class FloatingActionMenuBehavior(context: Context, attrs: AttributeSet)
|
||||
override def onStartNestedScroll(parent: CoordinatorLayout, child: FloatingActionMenu, directTargetChild: View,
|
||||
target: View, nestedScrollAxes: Int) = true
|
||||
override def onNestedScroll(parent: CoordinatorLayout, child: FloatingActionMenu, target: View, dxConsumed: Int,
|
||||
dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int) = {
|
||||
dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int) {
|
||||
super.onNestedScroll(parent, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed)
|
||||
val dy = dyConsumed + dyUnconsumed
|
||||
if (child.isMenuButtonHidden) {
|
||||
|
||||
@@ -37,12 +37,12 @@ class UndoSnackbarManager[T](view: View, undo: Iterator[(Int, T)] => Unit,
|
||||
commit: Iterator[(Int, T)] => Unit = null) {
|
||||
private val recycleBin = new ArrayBuffer[(Int, T)]
|
||||
private val removedCallback = new Snackbar.Callback {
|
||||
override def onDismissed(snackbar: Snackbar, event: Int) = {
|
||||
override def onDismissed(snackbar: Snackbar, event: Int) {
|
||||
event match {
|
||||
case Snackbar.Callback.DISMISS_EVENT_SWIPE | Snackbar.Callback.DISMISS_EVENT_MANUAL |
|
||||
Snackbar.Callback.DISMISS_EVENT_TIMEOUT =>
|
||||
if (commit != null) commit(recycleBin.iterator)
|
||||
recycleBin.clear
|
||||
recycleBin.clear()
|
||||
case _ =>
|
||||
}
|
||||
last = null
|
||||
@@ -50,7 +50,7 @@ class UndoSnackbarManager[T](view: View, undo: Iterator[(Int, T)] => Unit,
|
||||
}
|
||||
private var last: Snackbar = _
|
||||
|
||||
def remove(index: Int, item: T) = {
|
||||
def remove(index: Int, item: T) {
|
||||
recycleBin.append((index, item))
|
||||
val count = recycleBin.length
|
||||
last = Snackbar
|
||||
@@ -59,8 +59,8 @@ class UndoSnackbarManager[T](view: View, undo: Iterator[(Int, T)] => Unit,
|
||||
undo(recycleBin.reverseIterator)
|
||||
recycleBin.clear
|
||||
}): View.OnClickListener)
|
||||
last.show
|
||||
last.show()
|
||||
}
|
||||
|
||||
def flush = if (last != null) last.dismiss
|
||||
def flush(): Unit = if (last != null) last.dismiss()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user