diff --git a/project/plugins.sbt b/project/plugins.sbt
index c7b6fae9..82d45b05 100644
--- a/project/plugins.sbt
+++ b/project/plugins.sbt
@@ -1,8 +1,11 @@
resolvers += Resolver.url("scalasbt releases", new URL("http://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-snapshots"))(Resolver.ivyStylePatterns)
-addSbtPlugin("com.hanhuy.sbt" % "android-sdk-plugin" % "1.5.13")
+
+addSbtPlugin("com.hanhuy.sbt" % "android-sdk-plugin" % "1.5.14")
resolvers += "Sonatype snapshots" at "https://oss.sonatype.org/content/repositories/snapshots/"
+
addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.7.0-SNAPSHOT")
resolvers += Resolver.url("rtimush/sbt-plugin-snapshots", new URL("https://dl.bintray.com/rtimush/sbt-plugin-snapshots/"))(Resolver.ivyStylePatterns)
+
addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.1.9-6-g5a7705c")
diff --git a/src/main/res/layout/status_pref.xml b/src/main/res/layout/status_pref.xml
new file mode 100644
index 00000000..80e7fa5c
--- /dev/null
+++ b/src/main/res/layout/status_pref.xml
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/res/values-zh/strings.xml b/src/main/res/values-zh/strings.xml
index f7d28474..0fbd0408 100755
--- a/src/main/res/values-zh/strings.xml
+++ b/src/main/res/values-zh/strings.xml
@@ -75,14 +75,13 @@
网络流量
发送: \t%3$s\t↑\t%1$s/s\n接收: \t%4$s\t↓\t%2$s/s
-
- - 字节
-
- 点击检查是否接入互联网。
+
+ 检查网络连接
测试中……
- 已接入互联网。(延时:%d 毫秒)
+ 连接有效: 延时 %d 毫秒
+ 无互联网连接
失败:%s
- 状态码无效。(#%d)
+ 状态码无效(#%d)
配置文件
@@ -114,4 +113,9 @@
切换到 %s
使用当前配置
+
+ 发送:
+ 接收:
+ 检查网络连接
+
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index bc35aa22..89320c23 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -19,11 +19,12 @@
- Byte
- Bytes
- Tap to check Internet connection availability.
+ Check Connectivity
Testing…
- Internet connection available. (latency: %dms)
- Fail: %s
- Invalid status code. (#%d)
+ Success: %dms latency to Internet
+ Fail to detect internet connection: %s
+ Internet Unavailable
+ Error code: #%d
Server Settings
@@ -119,4 +120,9 @@
Connect to %s
Switch to %s
Use the current profile
+
+
+ Sent:
+ Received:
+ Check Connectivity
diff --git a/src/main/res/xml/pref_all.xml b/src/main/res/xml/pref_all.xml
index c5d7a3b5..23447138 100644
--- a/src/main/res/xml/pref_all.xml
+++ b/src/main/res/xml/pref_all.xml
@@ -8,7 +8,10 @@
-
+
diff --git a/src/main/scala/com/github/shadowsocks/Shadowsocks.scala b/src/main/scala/com/github/shadowsocks/Shadowsocks.scala
index e1a1cc3a..61e7f8a6 100644
--- a/src/main/scala/com/github/shadowsocks/Shadowsocks.scala
+++ b/src/main/scala/com/github/shadowsocks/Shadowsocks.scala
@@ -58,6 +58,7 @@ import android.view.{View, ViewGroup, ViewParent}
import android.widget._
import com.github.jorgecastilloprz.FABProgressCircle
import com.github.shadowsocks.aidl.IShadowsocksServiceCallback
+import com.github.shadowsocks.preferences._
import com.github.shadowsocks.database._
import com.github.shadowsocks.utils._
import com.google.android.gms.ads.{AdRequest, AdSize, AdView}
@@ -106,8 +107,9 @@ class Shadowsocks
var state = State.STOPPED
var currentProfile = new Profile
var vpnEnabled = -1
- var trafficCache: String = _
+ var trafficCache: Array[String] = _
var connectionTestResult: String = _
+ var connectionTestSuccess: Boolean = true
// Services
var currentServiceName = classOf[ShadowsocksNatService].getName
@@ -155,8 +157,9 @@ class Shadowsocks
})
}
def trafficUpdated(txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long) {
- trafficCache = getString(R.string.stat_summary).formatLocal(Locale.ENGLISH,
- TrafficMonitor.formatTraffic(txRate), TrafficMonitor.formatTraffic(rxRate),
+ trafficCache = Array(
+ "▲ " + TrafficMonitor.formatTraffic(txRate) + "/s",
+ "▼ " + TrafficMonitor.formatTraffic(rxRate) + "/s",
TrafficMonitor.formatTraffic(txTotal), TrafficMonitor.formatTraffic(rxTotal))
handler.post(updateTraffic)
}
@@ -165,10 +168,16 @@ class Shadowsocks
def updateTraffic(): Unit = if (trafficCache == null) callback.trafficUpdated(0, 0, 0, 0) else {
if (connectionTestResult == null) connectionTestResult = getString(R.string.connection_test_pending)
if (preferences.natSwitch.isChecked) {
- preferences.stat.setSummary(trafficCache)
+ preferences.stat.setSummary("")
} else {
- preferences.stat.setSummary(connectionTestResult + "\n" + trafficCache)
+ if (connectionTestSuccess) {
+ preferences.stat.setSummary(connectionTestResult)
+ } else {
+ preferences.stat.setSummary(getString(R.string.connection_test_fail))
+ Snackbar.make(findViewById(android.R.id.content), connectionTestResult, Snackbar.LENGTH_LONG).show
+ }
}
+ preferences.stat.asInstanceOf[StatusPreference].setRate(trafficCache(2), trafficCache(3), trafficCache(0), trafficCache(1))
}
def attachService: Unit = attachService(callback)
diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksSettings.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksSettings.scala
index a3a2d193..bd2902e0 100644
--- a/src/main/scala/com/github/shadowsocks/ShadowsocksSettings.scala
+++ b/src/main/scala/com/github/shadowsocks/ShadowsocksSettings.scala
@@ -78,11 +78,12 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan
addPreferencesFromResource(R.xml.pref_all)
getPreferenceManager.getSharedPreferences.registerOnSharedPreferenceChangeListener(this)
- stat = findPreference(Key.stat)
+ stat= findPreference(Key.stat)
stat.setOnPreferenceClickListener(_ => {
val id = synchronized {
testCount += 1
activity.connectionTestResult = getString(R.string.connection_test_testing)
+ activity.connectionTestSuccess = true
activity.updateTraffic()
testCount
}
@@ -96,6 +97,7 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan
conn.setUseCaches(false)
if (testCount == id) {
var result: String = null
+ var success: Boolean = true
try {
val start = currentTimeMillis
conn.getInputStream
@@ -105,9 +107,13 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan
result = getString(R.string.connection_test_available, elapsed: java.lang.Long)
else throw new Exception(getString(R.string.connection_test_error_status_code, code: Integer))
} catch {
- case e: Exception => result = getString(R.string.connection_test_error, e.getMessage)
+ case e: Exception => {
+ success = false
+ result = getString(R.string.connection_test_error, e.getMessage)
+ }
}
synchronized(if (testCount == id) {
+ activity.connectionTestSuccess = success
activity.connectionTestResult = result
activity.handler.post(activity.updateTraffic)
})
diff --git a/src/main/scala/com/github/shadowsocks/preferences/StatusPreference.scala b/src/main/scala/com/github/shadowsocks/preferences/StatusPreference.scala
new file mode 100644
index 00000000..2b198e5d
--- /dev/null
+++ b/src/main/scala/com/github/shadowsocks/preferences/StatusPreference.scala
@@ -0,0 +1,46 @@
+package com.github.shadowsocks.preferences
+
+import android.content.Context
+import android.preference.Preference
+import android.view.{View, ViewGroup, LayoutInflater}
+import android.util.AttributeSet
+import android.widget.TextView
+import com.github.shadowsocks.R
+
+/**
+ * @author madeye
+ */
+final class StatusPreference(context: Context, attrs: AttributeSet = null)
+ extends Preference(context, attrs) {
+ var txView: TextView = null
+ var rxView: TextView = null
+ var txRateView: TextView = null
+ var rxRateView: TextView = null
+
+ override def onCreateView(parent: ViewGroup): View = {
+ val li = getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE).asInstanceOf[LayoutInflater]
+ val view = li.inflate(R.layout.status_pref, parent, false)
+
+ txView = view.findViewById(R.id.tx).asInstanceOf[TextView]
+ rxView = view.findViewById(R.id.rx).asInstanceOf[TextView]
+ txRateView = view.findViewById(R.id.txRate).asInstanceOf[TextView]
+ rxRateView = view.findViewById(R.id.rxRate).asInstanceOf[TextView]
+
+ view
+ }
+
+ def setRate(tx: String, rx: String, txRate: String, rxRate: String) {
+ if (txView != null) {
+ txView.setText(tx)
+ }
+ if (rxView != null) {
+ rxView.setText(rx)
+ }
+ if (txRateView != null) {
+ txRateView.setText(txRate)
+ }
+ if (rxRateView != null) {
+ rxRateView.setText(rxRate)
+ }
+ }
+}