Refine Traffic Stat
This commit is contained in:
+4
-1
@@ -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")
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@android:id/widget_frame"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingEnd="?android:attr/scrollbarSize"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<TableLayout
|
||||
android:layout_marginLeft="15dip"
|
||||
android:layout_marginRight="6dip"
|
||||
android:layout_marginTop="6dip"
|
||||
android:layout_marginBottom="6dip"
|
||||
android:stretchColumns="3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<TextView
|
||||
android:layout_column="0"
|
||||
android:layout_span="2"
|
||||
android:id="@android:id/title"
|
||||
android:textSize="16sp"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:ellipsize="marquee"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
<TextView
|
||||
android:layout_column="3"
|
||||
android:id="@android:id/summary"
|
||||
android:textSize="14sp"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:ellipsize="marquee"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<TextView
|
||||
android:layout_column="0"
|
||||
style="@style/TextAppearance.AppCompat.Body2"
|
||||
android:ellipsize="marquee"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="24dp"
|
||||
android:gravity="end"
|
||||
android:text="@string/sent" />
|
||||
<TextView
|
||||
android:layout_column="1"
|
||||
android:id="@+id/tx"
|
||||
style="@style/TextAppearance.AppCompat.Caption"
|
||||
android:ellipsize="marquee"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:text="0 Byte" />
|
||||
<TextView
|
||||
android:layout_column="3"
|
||||
android:id="@+id/txRate"
|
||||
style="@style/TextAppearance.AppCompat.Caption"
|
||||
android:ellipsize="marquee"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:text="▲ 0 B/s" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<TextView
|
||||
android:layout_column="0"
|
||||
style="@style/TextAppearance.AppCompat.Body2"
|
||||
android:ellipsize="marquee"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="24dp"
|
||||
android:gravity="end"
|
||||
android:text="@string/received"/>
|
||||
<TextView
|
||||
android:layout_column="1"
|
||||
android:id="@+id/rx"
|
||||
style="@style/TextAppearance.AppCompat.Caption"
|
||||
android:ellipsize="marquee"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:text="0 Byte" />
|
||||
<TextView
|
||||
android:layout_column="3"
|
||||
android:id="@+id/rxRate"
|
||||
style="@style/TextAppearance.AppCompat.Caption"
|
||||
android:ellipsize="marquee"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:text="▼ 0 B/s" />
|
||||
</TableRow>
|
||||
|
||||
</TableLayout>
|
||||
</LinearLayout>
|
||||
@@ -75,14 +75,13 @@
|
||||
|
||||
<string name="stat">网络流量</string>
|
||||
<string name="stat_summary">发送: \t%3$s\t↑\t%1$s/s\n接收: \t%4$s\t↓\t%2$s/s</string>
|
||||
<plurals name="bytes">
|
||||
<item quantity="other">字节</item>
|
||||
</plurals>
|
||||
<string name="connection_test_pending">点击检查是否接入互联网。</string>
|
||||
|
||||
<string name="connection_test_pending">检查网络连接</string>
|
||||
<string name="connection_test_testing">测试中……</string>
|
||||
<string name="connection_test_available">已接入互联网。(延时:%d 毫秒)</string>
|
||||
<string name="connection_test_available">连接有效: 延时 %d 毫秒</string>
|
||||
<string name="connection_test_fail">无互联网连接</string>
|
||||
<string name="connection_test_error">失败:%s</string>
|
||||
<string name="connection_test_error_status_code">状态码无效。(#%d)</string>
|
||||
<string name="connection_test_error_status_code">状态码无效(#%d)</string>
|
||||
|
||||
<!-- profile -->
|
||||
<string name="profile_manager_dialog">配置文件</string>
|
||||
@@ -114,4 +113,9 @@
|
||||
<string name="stop_service">切换到 %s</string>
|
||||
<string name="profile_default">使用当前配置</string>
|
||||
|
||||
<!-- status -->
|
||||
<string name="sent">发送:</string>
|
||||
<string name="received">接收:</string>
|
||||
<string name="check_connectivity">检查网络连接</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -19,11 +19,12 @@
|
||||
<item quantity="one">Byte</item>
|
||||
<item quantity="other">Bytes</item>
|
||||
</plurals>
|
||||
<string name="connection_test_pending">Tap to check Internet connection availability.</string>
|
||||
<string name="connection_test_pending">Check Connectivity</string>
|
||||
<string name="connection_test_testing">Testing…</string>
|
||||
<string name="connection_test_available">Internet connection available. (latency: %dms)</string>
|
||||
<string name="connection_test_error">Fail: %s</string>
|
||||
<string name="connection_test_error_status_code">Invalid status code. (#%d)</string>
|
||||
<string name="connection_test_available">Success: %dms latency to Internet</string>
|
||||
<string name="connection_test_error">Fail to detect internet connection: %s</string>
|
||||
<string name="connection_test_fail">Internet Unavailable</string>
|
||||
<string name="connection_test_error_status_code">Error code: #%d</string>
|
||||
|
||||
<!-- proxy category -->
|
||||
<string name="proxy_cat">Server Settings</string>
|
||||
@@ -119,4 +120,9 @@
|
||||
<string name="start_service">Connect to %s</string>
|
||||
<string name="stop_service">Switch to %s</string>
|
||||
<string name="profile_default">Use the current profile</string>
|
||||
|
||||
<!-- status -->
|
||||
<string name="sent">Sent:</string>
|
||||
<string name="received">Received:</string>
|
||||
<string name="check_connectivity">Check Connectivity</string>
|
||||
</resources>
|
||||
|
||||
@@ -8,7 +8,10 @@
|
||||
<intent android:action="com.github.shadowsocks.ProfileManagerActivity"/>
|
||||
</Preference>
|
||||
|
||||
<Preference android:key="stat" android:title="@string/stat"/>
|
||||
<com.github.shadowsocks.preferences.StatusPreference
|
||||
android:key="stat"
|
||||
android:summary="@string/check_connectivity"
|
||||
android:title="@string/stat"/>
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user