Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fbdf2dbf04 | ||
|
|
c7dd9aeeca | ||
|
|
eaac098027 | ||
|
|
65635c6b93 | ||
|
|
187cb28d15 | ||
|
|
2840a75c92 | ||
|
|
95e214ef11 | ||
|
|
217ed797d9 | ||
|
|
d337f0e2e4 | ||
|
|
713ff53030 | ||
|
|
35f17f5338 | ||
|
|
172c0b240f | ||
|
|
e9406080e2 | ||
|
|
7f937a8ee6 |
@@ -30,7 +30,7 @@ libraryDependencies ++= Seq(
|
||||
"dnsjava" % "dnsjava" % "2.1.7",
|
||||
"com.github.kevinsawicki" % "http-request" % "6.0",
|
||||
"commons-net" % "commons-net" % "3.4",
|
||||
"eu.chainfire" % "libsuperuser" % "1.0.0.201510071325",
|
||||
"eu.chainfire" % "libsuperuser" % "1.0.0.201602011018",
|
||||
"com.google.zxing" % "android-integration" % "3.2.1",
|
||||
"net.glxn.qrgen" % "android" % "2.0",
|
||||
"com.google.android.gms" % "play-services-base" % "8.4.0",
|
||||
|
||||
@@ -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.16")
|
||||
|
||||
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")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.github.shadowsocks"
|
||||
android:versionCode="128"
|
||||
android:versionName="2.9.6">
|
||||
android:versionCode="129"
|
||||
android:versionName="2.9.7">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
|
||||
@@ -45,6 +45,6 @@ public class System {
|
||||
|
||||
public static native int exec(String cmd);
|
||||
public static native String getABI();
|
||||
public static native int sendfd(int fd);
|
||||
public static native int sendfd(int fd, String path);
|
||||
public static native void jniclose(int fd);
|
||||
}
|
||||
|
||||
@@ -64,9 +64,10 @@ void Java_com_github_shadowsocks_system_jniclose(JNIEnv *env, jobject thiz, jint
|
||||
close(fd);
|
||||
}
|
||||
|
||||
jint Java_com_github_shadowsocks_system_sendfd(JNIEnv *env, jobject thiz, jint tun_fd) {
|
||||
jint Java_com_github_shadowsocks_system_sendfd(JNIEnv *env, jobject thiz, jint tun_fd, jstring path) {
|
||||
int fd;
|
||||
struct sockaddr_un addr;
|
||||
const char *sock_str = env->GetStringUTFChars(path, 0);
|
||||
|
||||
if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
|
||||
LOGE("socket() failed: %s (socket fd = %d)\n", strerror(errno), fd);
|
||||
@@ -75,7 +76,7 @@ jint Java_com_github_shadowsocks_system_sendfd(JNIEnv *env, jobject thiz, jint t
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy(addr.sun_path, "/data/data/com.github.shadowsocks/sock_path", sizeof(addr.sun_path)-1);
|
||||
strncpy(addr.sun_path, sock_str, sizeof(addr.sun_path)-1);
|
||||
|
||||
if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
|
||||
LOGE("connect() failed: %s (fd = %d)\n", strerror(errno), fd);
|
||||
@@ -90,6 +91,7 @@ jint Java_com_github_shadowsocks_system_sendfd(JNIEnv *env, jobject thiz, jint t
|
||||
}
|
||||
|
||||
close(fd);
|
||||
env->ReleaseStringUTFChars(path, sock_str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -98,7 +100,7 @@ static const char *classPathName = "com/github/shadowsocks/System";
|
||||
static JNINativeMethod method_table[] = {
|
||||
{ "jniclose", "(I)V",
|
||||
(void*) Java_com_github_shadowsocks_system_jniclose },
|
||||
{ "sendfd", "(I)I",
|
||||
{ "sendfd", "(ILjava/lang/String;)I",
|
||||
(void*) Java_com_github_shadowsocks_system_sendfd },
|
||||
{ "exec", "(Ljava/lang/String;)I",
|
||||
(void*) Java_com_github_shadowsocks_system_exec },
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path
|
||||
android:fillColor="#fff"
|
||||
android:pathData="M17.68,9l-1.59,7L12.7,14.89l5-5.93M10,10.08l-3.57,3L5,12.55l5-2.47M21.25,2.28L0,12.8l6.83,2.57,9.76-8.21L9.26,15.89l8.29,2.67,3.7-16.27h0Z" />
|
||||
<path
|
||||
android:fillColor="#fff"
|
||||
android:pathData="M 9.45 17.56 L 9.46 22 L 12.09 18.41 L 9.45 17.56 L 9.45 17.56 Z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path
|
||||
android:fillColor="#fff"
|
||||
android:pathData="M 21.25 2.28 L 17.55 18.55 L 9.26 15.89 L 16.58 7.16 L 6.83 15.37 L 0 12.8 L 21.25 2.28 Z" />
|
||||
<path
|
||||
android:fillColor="#fff"
|
||||
android:pathData="M 9.45 17.56 L 12.09 18.41 L 9.46 22 L 9.45 17.56 Z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path
|
||||
android:fillColor="#fff"
|
||||
android:pathData="M 9.45 17.56 L 9.46 22 L 12.09 18.41 L 9.45 17.56 L 9.45 17.56 Z" />
|
||||
<path
|
||||
android:strokeColor="#fff"
|
||||
android:strokeWidth="2"
|
||||
android:strokeMiterLimit="10"
|
||||
android:pathData="M0.71,2.12L21.88,23.29Z" />
|
||||
<path
|
||||
android:fillColor="#fff"
|
||||
android:pathData="M 13 10.17 L 16.58 7.16 L 13.57 10.75 L 14.99 12.16 L 17.68 8.96 L 16.59 13.76 L 18.26 15.43 L 21.25 2.28 L 10.45 7.62 L 13 10.17 Z" />
|
||||
<path
|
||||
android:fillColor="#fff"
|
||||
android:pathData="M 15.93 15.93 L 12.71 14.89 L 13.7 13.7 L 12.28 12.28 L 9.26 15.89 L 17.55 18.55 L 17.74 17.74 L 15.93 15.93 Z" />
|
||||
<path
|
||||
android:fillColor="#fff"
|
||||
android:pathData="M8.56,8.56L0,12.8l6.83,2.57,4.64-3.9ZM6.44,13.08L5,12.55l5-2.47Z" />
|
||||
</vector>
|
||||
|
Before Width: | Height: | Size: 297 B |
|
Before Width: | Height: | Size: 462 B |
|
Before Width: | Height: | Size: 425 B |
|
After Width: | Height: | Size: 430 B |
|
After Width: | Height: | Size: 387 B |
|
After Width: | Height: | Size: 468 B |
|
Before Width: | Height: | Size: 209 B |
|
Before Width: | Height: | Size: 330 B |
|
Before Width: | Height: | Size: 276 B |
|
After Width: | Height: | Size: 343 B |
|
After Width: | Height: | Size: 312 B |
|
After Width: | Height: | Size: 359 B |
|
Before Width: | Height: | Size: 354 B |
|
Before Width: | Height: | Size: 593 B |
|
Before Width: | Height: | Size: 537 B |
|
After Width: | Height: | Size: 571 B |
|
After Width: | Height: | Size: 518 B |
|
After Width: | Height: | Size: 605 B |
|
Before Width: | Height: | Size: 517 B |
|
Before Width: | Height: | Size: 859 B |
|
Before Width: | Height: | Size: 785 B |
|
After Width: | Height: | Size: 825 B |
|
After Width: | Height: | Size: 789 B |
|
After Width: | Height: | Size: 835 B |
|
Before Width: | Height: | Size: 660 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
@@ -19,7 +19,7 @@
|
||||
<android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:backgroundTint="@color/material_blue_grey_700"
|
||||
android:src="@drawable/ic_cloud_off"
|
||||
android:src="@drawable/ic_start_idle"
|
||||
app:pressedTranslationZ="6dp" app:borderWidth="0dp" />
|
||||
</com.github.jorgecastilloprz.FABProgressCircle>
|
||||
</RelativeLayout>
|
||||
|
||||
@@ -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</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>
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ trait BaseService extends Service {
|
||||
|
||||
startService(new Intent(getContext, getClass))
|
||||
TrafficMonitor.reset()
|
||||
trafficMonitorThread = new TrafficMonitorThread()
|
||||
trafficMonitorThread = new TrafficMonitorThread(getApplicationContext)
|
||||
trafficMonitorThread.start()
|
||||
}
|
||||
|
||||
@@ -178,6 +178,9 @@ trait BaseService extends Service {
|
||||
})
|
||||
}
|
||||
|
||||
// Service of shadowsocks should always be started explicitly
|
||||
override def onStartCommand(intent: Intent, flags: Int, startId: Int): Int = Service.START_NOT_STICKY
|
||||
|
||||
protected def changeState(s: Int, msg: String) {
|
||||
val handler = new Handler(getContext.getMainLooper)
|
||||
handler.post(() => if (state != s) {
|
||||
|
||||
@@ -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
|
||||
@@ -117,7 +119,7 @@ class Shadowsocks
|
||||
s match {
|
||||
case State.CONNECTING =>
|
||||
fab.setBackgroundTintList(greyTint)
|
||||
fab.setImageResource(R.drawable.ic_cloud_queue)
|
||||
fab.setImageResource(R.drawable.ic_start_busy)
|
||||
fab.setEnabled(false)
|
||||
fabProgressCircle.show()
|
||||
preferences.setEnabled(false)
|
||||
@@ -142,11 +144,12 @@ class Shadowsocks
|
||||
if (m == getString(R.string.nat_no_root)) snackbar.setAction(R.string.switch_to_vpn,
|
||||
(_ => preferences.natSwitch.setChecked(false)): View.OnClickListener)
|
||||
snackbar.show
|
||||
Log.e(Shadowsocks.TAG, "Error to start VPN service: " + m)
|
||||
}
|
||||
preferences.setEnabled(true)
|
||||
case State.STOPPING =>
|
||||
fab.setBackgroundTintList(greyTint)
|
||||
fab.setImageResource(R.drawable.ic_cloud_queue)
|
||||
fab.setImageResource(R.drawable.ic_start_busy)
|
||||
fab.setEnabled(false)
|
||||
if (state == State.CONNECTED) fabProgressCircle.show() // ignore for stopped
|
||||
preferences.setEnabled(false)
|
||||
@@ -155,8 +158,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 +169,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)
|
||||
@@ -216,7 +226,7 @@ class Shadowsocks
|
||||
|
||||
private def changeSwitch(checked: Boolean) {
|
||||
serviceStarted = checked
|
||||
fab.setImageResource(if (checked) R.drawable.ic_cloud else R.drawable.ic_cloud_off)
|
||||
fab.setImageResource(if (checked) R.drawable.ic_start_connected else R.drawable.ic_start_idle)
|
||||
if (fab.isEnabled) {
|
||||
fab.setEnabled(false)
|
||||
handler.postDelayed(() => fab.setEnabled(true), 1000)
|
||||
@@ -253,7 +263,7 @@ class Shadowsocks
|
||||
} else {
|
||||
in = assetManager.open(file)
|
||||
}
|
||||
out = new FileOutputStream(Path.BASE + file)
|
||||
out = new FileOutputStream(getApplicationInfo().dataDir + "/" + file)
|
||||
copyFile(in, out)
|
||||
in.close()
|
||||
in = null
|
||||
@@ -283,8 +293,8 @@ class Shadowsocks
|
||||
val cmd = new ArrayBuffer[String]()
|
||||
|
||||
for (task <- Array("ss-local", "ss-tunnel", "pdnsd", "redsocks", "tun2socks")) {
|
||||
cmd.append("chmod 666 %s%s-nat.pid".formatLocal(Locale.ENGLISH, Path.BASE, task))
|
||||
cmd.append("chmod 666 %s%s-vpn.pid".formatLocal(Locale.ENGLISH, Path.BASE, task))
|
||||
cmd.append("chmod 666 %s/%s-nat.pid".formatLocal(Locale.ENGLISH, getApplicationInfo().dataDir, task))
|
||||
cmd.append("chmod 666 %s/%s-vpn.pid".formatLocal(Locale.ENGLISH, getApplicationInfo().dataDir, task))
|
||||
}
|
||||
|
||||
if (ShadowsocksApplication.isVpnEnabled) {
|
||||
@@ -297,19 +307,19 @@ class Shadowsocks
|
||||
|
||||
for (task <- Array("ss-local", "ss-tunnel", "pdnsd", "redsocks", "tun2socks")) {
|
||||
try {
|
||||
val pid_nat = scala.io.Source.fromFile(Path.BASE + task + "-nat.pid").mkString.trim.toInt
|
||||
val pid_vpn = scala.io.Source.fromFile(Path.BASE + task + "-vpn.pid").mkString.trim.toInt
|
||||
val pid_nat = scala.io.Source.fromFile(getApplicationInfo().dataDir + "/" + task + "-nat.pid").mkString.trim.toInt
|
||||
val pid_vpn = scala.io.Source.fromFile(getApplicationInfo().dataDir + "/" + task + "-vpn.pid").mkString.trim.toInt
|
||||
cmd.append("kill -9 %d".formatLocal(Locale.ENGLISH, pid_nat))
|
||||
cmd.append("kill -9 %d".formatLocal(Locale.ENGLISH, pid_vpn))
|
||||
Process.killProcess(pid_nat)
|
||||
Process.killProcess(pid_vpn)
|
||||
} catch {
|
||||
case e: Throwable => Log.e(Shadowsocks.TAG, "unable to kill " + task)
|
||||
case e: Throwable => // Ignore
|
||||
}
|
||||
cmd.append("rm -f %s%s-nat.pid".formatLocal(Locale.ENGLISH, Path.BASE, task))
|
||||
cmd.append("rm -f %s%s-nat.conf".formatLocal(Locale.ENGLISH, Path.BASE, task))
|
||||
cmd.append("rm -f %s%s-vpn.pid".formatLocal(Locale.ENGLISH, Path.BASE, task))
|
||||
cmd.append("rm -f %s%s-vpn.conf".formatLocal(Locale.ENGLISH, Path.BASE, task))
|
||||
cmd.append("rm -f %s/%s-nat.pid".formatLocal(Locale.ENGLISH, getApplicationInfo().dataDir, task))
|
||||
cmd.append("rm -f %s/%s-nat.conf".formatLocal(Locale.ENGLISH, getApplicationInfo().dataDir, task))
|
||||
cmd.append("rm -f %s/%s-vpn.pid".formatLocal(Locale.ENGLISH, getApplicationInfo().dataDir, task))
|
||||
cmd.append("rm -f %s/%s-vpn.conf".formatLocal(Locale.ENGLISH, getApplicationInfo().dataDir, task))
|
||||
}
|
||||
if (ShadowsocksApplication.isVpnEnabled) Console.runCommand(cmd.toArray) else {
|
||||
Console.runRootCommand(cmd.toArray)
|
||||
@@ -418,25 +428,25 @@ class Shadowsocks
|
||||
case State.CONNECTING =>
|
||||
fab.setBackgroundTintList(greyTint)
|
||||
serviceStarted = false
|
||||
fab.setImageResource(R.drawable.ic_cloud_queue)
|
||||
fab.setImageResource(R.drawable.ic_start_busy)
|
||||
preferences.setEnabled(false)
|
||||
fabProgressCircle.show()
|
||||
case State.CONNECTED =>
|
||||
fab.setBackgroundTintList(greenTint)
|
||||
serviceStarted = true
|
||||
fab.setImageResource(R.drawable.ic_cloud)
|
||||
fab.setImageResource(R.drawable.ic_start_connected)
|
||||
preferences.setEnabled(false)
|
||||
fabProgressCircle.postDelayed(hideCircle, 100)
|
||||
case State.STOPPING =>
|
||||
fab.setBackgroundTintList(greyTint)
|
||||
serviceStarted = false
|
||||
fab.setImageResource(R.drawable.ic_cloud_queue)
|
||||
fab.setImageResource(R.drawable.ic_start_busy)
|
||||
preferences.setEnabled(false)
|
||||
fabProgressCircle.show()
|
||||
case _ =>
|
||||
fab.setBackgroundTintList(greyTint)
|
||||
serviceStarted = false
|
||||
fab.setImageResource(R.drawable.ic_cloud_off)
|
||||
fab.setImageResource(R.drawable.ic_start_idle)
|
||||
preferences.setEnabled(true)
|
||||
fabProgressCircle.postDelayed(hideCircle, 100)
|
||||
}
|
||||
@@ -493,7 +503,7 @@ class Shadowsocks
|
||||
|
||||
val ab = new ArrayBuffer[String]
|
||||
for (executable <- Shadowsocks.EXECUTABLES) {
|
||||
ab.append("chmod 755 " + Path.BASE + executable)
|
||||
ab.append("chmod 755 " + getApplicationInfo().dataDir + "/" + executable)
|
||||
}
|
||||
Console.runCommand(ab.toArray)
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ class ShadowsocksNatService extends BaseService {
|
||||
case Route.BYPASS_LAN => getResources.getStringArray(R.array.private_route)
|
||||
case Route.BYPASS_CHN => getResources.getStringArray(R.array.chn_route_full)
|
||||
}
|
||||
ConfigUtils.printToFile(new File(Path.BASE + "acl.list"))(p => {
|
||||
ConfigUtils.printToFile(new File(getApplicationInfo.dataDir + "/acl.list"))(p => {
|
||||
acl.foreach(item => p.println(item))
|
||||
})
|
||||
}
|
||||
@@ -176,21 +176,22 @@ class ShadowsocksNatService extends BaseService {
|
||||
val conf = ConfigUtils
|
||||
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, config.proxy, config.remotePort, config.localPort,
|
||||
config.sitekey, config.encMethod, 600)
|
||||
ConfigUtils.printToFile(new File(Path.BASE + "ss-local-nat.conf"))(p => {
|
||||
ConfigUtils.printToFile(new File(getApplicationInfo.dataDir + "/ss-local-nat.conf"))(p => {
|
||||
p.println(conf)
|
||||
})
|
||||
|
||||
val cmd = new ArrayBuffer[String]
|
||||
cmd += (Path.BASE + "ss-local"
|
||||
cmd += (getApplicationInfo.dataDir + "/ss-local"
|
||||
, "-b" , "127.0.0.1"
|
||||
, "-t" , "600"
|
||||
, "-c" , Path.BASE + "ss-local-nat.conf")
|
||||
, "-P", getApplicationInfo.dataDir
|
||||
, "-c" , getApplicationInfo.dataDir + "/ss-local-nat.conf")
|
||||
|
||||
if (config.isAuth) cmd += "-A"
|
||||
|
||||
if (config.route != Route.ALL) {
|
||||
cmd += "--acl"
|
||||
cmd += (Path.BASE + "acl.list")
|
||||
cmd += (getApplicationInfo.dataDir + "/acl.list")
|
||||
}
|
||||
|
||||
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
|
||||
@@ -205,16 +206,17 @@ class ShadowsocksNatService extends BaseService {
|
||||
val conf = ConfigUtils
|
||||
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, config.proxy, config.remotePort, 8153,
|
||||
config.sitekey, config.encMethod, 10)
|
||||
ConfigUtils.printToFile(new File(Path.BASE + "ss-tunnel-nat.conf"))(p => {
|
||||
ConfigUtils.printToFile(new File(getApplicationInfo.dataDir + "/ss-tunnel-nat.conf"))(p => {
|
||||
p.println(conf)
|
||||
})
|
||||
val cmd = new ArrayBuffer[String]
|
||||
cmd += (Path.BASE + "ss-tunnel"
|
||||
cmd += (getApplicationInfo.dataDir + "/ss-tunnel"
|
||||
, "-u"
|
||||
, "-t" , "10"
|
||||
, "-b" , "127.0.0.1"
|
||||
, "-L" , "8.8.8.8:53"
|
||||
, "-c" , Path.BASE + "ss-tunnel-nat.conf")
|
||||
, "-P" , getApplicationInfo.dataDir
|
||||
, "-c" , getApplicationInfo.dataDir + "/ss-tunnel-nat.conf")
|
||||
|
||||
cmd += ("-l" , "8153")
|
||||
|
||||
@@ -231,17 +233,18 @@ class ShadowsocksNatService extends BaseService {
|
||||
val conf = ConfigUtils
|
||||
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, config.proxy, config.remotePort, 8163,
|
||||
config.sitekey, config.encMethod, 10)
|
||||
ConfigUtils.printToFile(new File(Path.BASE + "ss-tunnel-nat.conf"))(p => {
|
||||
ConfigUtils.printToFile(new File(getApplicationInfo.dataDir + "/ss-tunnel-nat.conf"))(p => {
|
||||
p.println(conf)
|
||||
})
|
||||
val cmdBuf = new ArrayBuffer[String]
|
||||
cmdBuf += (Path.BASE + "ss-tunnel"
|
||||
cmdBuf += (getApplicationInfo.dataDir + "/ss-tunnel"
|
||||
, "-u"
|
||||
, "-t" , "10"
|
||||
, "-b" , "127.0.0.1"
|
||||
, "-l" , "8163"
|
||||
, "-L" , "8.8.8.8:53"
|
||||
, "-c" , Path.BASE + "ss-tunnel-nat.conf")
|
||||
, "-P", getApplicationInfo.dataDir
|
||||
, "-c" , getApplicationInfo.dataDir + "/ss-tunnel-nat.conf")
|
||||
|
||||
if (config.isAuth) cmdBuf += "-A"
|
||||
|
||||
@@ -259,17 +262,17 @@ class ShadowsocksNatService extends BaseService {
|
||||
val conf = if (config.route == Route.BYPASS_CHN) {
|
||||
val reject = ConfigUtils.getRejectList(getContext)
|
||||
val blackList = ConfigUtils.getBlackList(getContext)
|
||||
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, "127.0.0.1", 8153,
|
||||
reject, blackList, 8163, "")
|
||||
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir,
|
||||
"127.0.0.1", 8153, reject, blackList, 8163, "")
|
||||
} else {
|
||||
ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, "127.0.0.1", 8153,
|
||||
8163, "")
|
||||
ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir,
|
||||
"127.0.0.1", 8153, 8163, "")
|
||||
}
|
||||
|
||||
ConfigUtils.printToFile(new File(Path.BASE + "pdnsd-nat.conf"))(p => {
|
||||
ConfigUtils.printToFile(new File(getApplicationInfo.dataDir + "/pdnsd-nat.conf"))(p => {
|
||||
p.println(conf)
|
||||
})
|
||||
val cmd = Path.BASE + "pdnsd -c " + Path.BASE + "pdnsd-nat.conf"
|
||||
val cmd = getApplicationInfo.dataDir + "/pdnsd -c " + getApplicationInfo.dataDir + "/pdnsd-nat.conf"
|
||||
|
||||
if (BuildConfig.DEBUG) Log.d(TAG, cmd)
|
||||
|
||||
@@ -293,9 +296,9 @@ class ShadowsocksNatService extends BaseService {
|
||||
|
||||
def startRedsocksDaemon() {
|
||||
val conf = ConfigUtils.REDSOCKS.formatLocal(Locale.ENGLISH, config.localPort)
|
||||
val cmd = Path.BASE + "redsocks -c %sredsocks-nat.conf"
|
||||
.formatLocal(Locale.ENGLISH, Path.BASE, Path.BASE)
|
||||
ConfigUtils.printToFile(new File(Path.BASE + "redsocks-nat.conf"))(p => {
|
||||
val cmd = "%s/redsocks -c %s/redsocks-nat.conf"
|
||||
.formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir, getApplicationInfo.dataDir)
|
||||
ConfigUtils.printToFile(new File(getApplicationInfo.dataDir + "/redsocks-nat.conf"))(p => {
|
||||
p.println(conf)
|
||||
})
|
||||
|
||||
@@ -332,8 +335,6 @@ class ShadowsocksNatService extends BaseService {
|
||||
ConfigUtils.refresh(this)
|
||||
}
|
||||
|
||||
override def onStartCommand(intent: Intent, flags: Int, startId: Int): Int = Service.START_STICKY
|
||||
|
||||
def killProcesses() {
|
||||
if (sslocalProcess != null) {
|
||||
sslocalProcess.destroy()
|
||||
@@ -393,13 +394,10 @@ class ShadowsocksNatService extends BaseService {
|
||||
}
|
||||
|
||||
override def startRunner(config: Config) {
|
||||
|
||||
changeState(State.CONNECTING)
|
||||
if (!Console.isRoot) {
|
||||
changeState(State.STOPPED, getString(R.string.nat_no_root))
|
||||
return
|
||||
}
|
||||
|
||||
super.startRunner(config)
|
||||
|
||||
// register close receiver
|
||||
@@ -413,6 +411,8 @@ class ShadowsocksNatService extends BaseService {
|
||||
registerReceiver(closeReceiver, filter)
|
||||
|
||||
ShadowsocksApplication.track(TAG, "start")
|
||||
|
||||
changeState(State.CONNECTING)
|
||||
|
||||
ThrowableFuture {
|
||||
if (config.proxy == "198.199.101.152") {
|
||||
|
||||
@@ -30,7 +30,6 @@ class ShadowsocksNotification(private val service: BaseService, profileName: Str
|
||||
}
|
||||
private var lockReceiver: BroadcastReceiver = _
|
||||
private var callbackRegistered: Boolean = _
|
||||
private var started: Boolean = _
|
||||
|
||||
private val builder = new NotificationCompat.Builder(service)
|
||||
.setWhen(0)
|
||||
@@ -77,9 +76,8 @@ class ShadowsocksNotification(private val service: BaseService, profileName: Str
|
||||
show()
|
||||
} else if (forceShow) show()
|
||||
|
||||
def show() = if (started) nm.notify(1, builder.build) else {
|
||||
def show() = {
|
||||
service.startForeground(1, builder.build)
|
||||
started = true
|
||||
}
|
||||
|
||||
def destroy() {
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
|
||||
@@ -261,7 +261,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
var tries = 1
|
||||
while (tries < 5) {
|
||||
Thread.sleep(1000 * tries)
|
||||
if (System.sendfd(fd) != -1) {
|
||||
if (System.sendfd(fd, getApplicationInfo.dataDir + "/sock_path") != -1) {
|
||||
return true
|
||||
}
|
||||
tries += 1
|
||||
@@ -277,7 +277,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
case Route.BYPASS_LAN => getResources.getStringArray(R.array.private_route)
|
||||
case Route.BYPASS_CHN => getResources.getStringArray(R.array.chn_route_full)
|
||||
}
|
||||
ConfigUtils.printToFile(new File(Path.BASE + "acl.list"))(p => {
|
||||
ConfigUtils.printToFile(new File(getApplicationInfo.dataDir + "/acl.list"))(p => {
|
||||
acl.foreach(item => p.println(item))
|
||||
})
|
||||
}
|
||||
@@ -285,21 +285,22 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
val conf = ConfigUtils
|
||||
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, config.proxy, config.remotePort, config.localPort,
|
||||
config.sitekey, config.encMethod, 600)
|
||||
ConfigUtils.printToFile(new File(Path.BASE + "ss-local-vpn.conf"))(p => {
|
||||
ConfigUtils.printToFile(new File(getApplicationInfo.dataDir + "/ss-local-vpn.conf"))(p => {
|
||||
p.println(conf)
|
||||
})
|
||||
|
||||
val cmd = new ArrayBuffer[String]
|
||||
cmd += (Path.BASE + "ss-local", "-V", "-u"
|
||||
cmd += (getApplicationInfo.dataDir + "/ss-local", "-V", "-u"
|
||||
, "-b", "127.0.0.1"
|
||||
, "-t", "600"
|
||||
, "-c", Path.BASE + "ss-local-vpn.conf")
|
||||
, "-P", getApplicationInfo.dataDir
|
||||
, "-c", getApplicationInfo.dataDir + "/ss-local-vpn.conf")
|
||||
|
||||
if (config.isAuth) cmd += "-A"
|
||||
|
||||
if (config.route != Route.ALL) {
|
||||
cmd += "--acl"
|
||||
cmd += (Path.BASE + "acl.list")
|
||||
cmd += (getApplicationInfo.dataDir + "/acl.list")
|
||||
}
|
||||
|
||||
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
|
||||
@@ -314,18 +315,19 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
val conf = ConfigUtils
|
||||
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, config.proxy, config.remotePort, 8163,
|
||||
config.sitekey, config.encMethod, 10)
|
||||
ConfigUtils.printToFile(new File(Path.BASE + "ss-tunnel-vpn.conf"))(p => {
|
||||
ConfigUtils.printToFile(new File(getApplicationInfo.dataDir + "/ss-tunnel-vpn.conf"))(p => {
|
||||
p.println(conf)
|
||||
})
|
||||
val cmd = new ArrayBuffer[String]
|
||||
cmd += (Path.BASE + "ss-tunnel"
|
||||
cmd += (getApplicationInfo.dataDir + "/ss-tunnel"
|
||||
, "-V"
|
||||
, "-u"
|
||||
, "-t", "10"
|
||||
, "-b", "127.0.0.1"
|
||||
, "-l", "8163"
|
||||
, "-L", "8.8.8.8:53"
|
||||
, "-c", Path.BASE + "ss-tunnel-vpn.conf")
|
||||
, "-P", getApplicationInfo.dataDir
|
||||
, "-c", getApplicationInfo.dataDir + "/ss-tunnel-vpn.conf")
|
||||
|
||||
if (config.isAuth) cmd += "-A"
|
||||
|
||||
@@ -343,17 +345,17 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
if (config.route == Route.BYPASS_CHN) {
|
||||
val reject = ConfigUtils.getRejectList(getContext)
|
||||
val blackList = ConfigUtils.getBlackList(getContext)
|
||||
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, "0.0.0.0", 8153,
|
||||
reject, blackList, 8163, ipv6)
|
||||
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir,
|
||||
"0.0.0.0", 8153, reject, blackList, 8163, ipv6)
|
||||
} else {
|
||||
ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, "0.0.0.0", 8153,
|
||||
8163, ipv6)
|
||||
ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir,
|
||||
"0.0.0.0", 8153, 8163, ipv6)
|
||||
}
|
||||
}
|
||||
ConfigUtils.printToFile(new File(Path.BASE + "pdnsd-vpn.conf"))(p => {
|
||||
ConfigUtils.printToFile(new File(getApplicationInfo.dataDir + "/pdnsd-vpn.conf"))(p => {
|
||||
p.println(conf)
|
||||
})
|
||||
val cmd = Path.BASE + "pdnsd -c " + Path.BASE + "pdnsd-vpn.conf"
|
||||
val cmd = getApplicationInfo.dataDir + "/pdnsd -c " + getApplicationInfo.dataDir + "/pdnsd-vpn.conf"
|
||||
|
||||
if (BuildConfig.DEBUG) Log.d(TAG, cmd)
|
||||
|
||||
@@ -428,16 +430,17 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
|
||||
val fd = conn.getFd
|
||||
|
||||
var cmd = (Path.BASE +
|
||||
"tun2socks --netif-ipaddr %s "
|
||||
var cmd = (getApplicationInfo.dataDir +
|
||||
"/tun2socks --netif-ipaddr %s "
|
||||
+ "--netif-netmask 255.255.255.0 "
|
||||
+ "--socks-server-addr 127.0.0.1:%d "
|
||||
+ "--tunfd %d "
|
||||
+ "--tunmtu %d "
|
||||
+ "--sock-path %s "
|
||||
+ "--loglevel 3")
|
||||
.formatLocal(Locale.ENGLISH,
|
||||
PRIVATE_VLAN.formatLocal(Locale.ENGLISH, "2"),
|
||||
config.localPort, fd, VPN_MTU)
|
||||
config.localPort, fd, VPN_MTU, getApplicationInfo.dataDir + "/sock_path")
|
||||
|
||||
if (config.isIpv6)
|
||||
cmd += " --netif-ip6addr " + PRIVATE_VLAN6.formatLocal(Locale.ENGLISH, "2")
|
||||
|
||||
@@ -53,7 +53,7 @@ class ShadowsocksVpnThread(vpnService: ShadowsocksVpnService) extends Thread {
|
||||
import ShadowsocksVpnThread._
|
||||
|
||||
val TAG = "ShadowsocksVpnService"
|
||||
val PATH = "/data/data/com.github.shadowsocks/protect_path"
|
||||
lazy val PATH = vpnService.getApplicationInfo.dataDir + "/protect_path"
|
||||
|
||||
@volatile var isRunning: Boolean = true
|
||||
@volatile var serverSocket: LocalServerSocket = null
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
package com.github.shadowsocks
|
||||
|
||||
import android.content.{BroadcastReceiver, Context, Intent}
|
||||
import android.os.Handler
|
||||
import com.github.shadowsocks.helper.TaskerSettings
|
||||
import com.github.shadowsocks.utils.Utils
|
||||
|
||||
@@ -55,6 +56,10 @@ class TaskerReceiver extends BroadcastReceiver {
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
if (settings.switchOn) Utils.startSsService(context) else if (!switched) Utils.stopSsService(context)
|
||||
val handler = new Handler(context.getMainLooper)
|
||||
handler.postDelayed(() => {
|
||||
if (settings.switchOn) Utils.startSsService(context)
|
||||
else if (!switched) Utils.stopSsService(context)
|
||||
}, 3000)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,7 +66,7 @@ object ConfigUtils {
|
||||
"""
|
||||
|global {
|
||||
| perm_cache = 2048;
|
||||
| cache_dir = "/data/data/com.github.shadowsocks";
|
||||
| cache_dir = "%s";
|
||||
| server_ip = %s;
|
||||
| server_port = %d;
|
||||
| query_method = tcp_only;
|
||||
@@ -100,7 +100,7 @@ object ConfigUtils {
|
||||
"""
|
||||
|global {
|
||||
| perm_cache = 2048;
|
||||
| cache_dir = "/data/data/com.github.shadowsocks";
|
||||
| cache_dir = "%s";
|
||||
| server_ip = %s;
|
||||
| server_port = %d;
|
||||
| query_method = tcp_only;
|
||||
@@ -143,7 +143,7 @@ object ConfigUtils {
|
||||
"""
|
||||
|global {
|
||||
| perm_cache = 2048;
|
||||
| cache_dir = "/data/data/com.github.shadowsocks";
|
||||
| cache_dir = "%s";
|
||||
| server_ip = %s;
|
||||
| server_port = %d;
|
||||
| query_method = tcp_only;
|
||||
|
||||
@@ -55,10 +55,6 @@ object Msg {
|
||||
val VPN_ERROR = 6
|
||||
}
|
||||
|
||||
object Path {
|
||||
val BASE = "/data/data/com.github.shadowsocks/"
|
||||
}
|
||||
|
||||
object Key {
|
||||
val profileId = "profileId"
|
||||
val profileName = "profileName"
|
||||
|
||||
@@ -43,13 +43,14 @@ import java.io.{File, IOException}
|
||||
import java.nio.{ByteBuffer, ByteOrder}
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
import android.content.Context
|
||||
import android.net.{LocalServerSocket, LocalSocket, LocalSocketAddress}
|
||||
import android.util.Log
|
||||
|
||||
class TrafficMonitorThread() extends Thread {
|
||||
class TrafficMonitorThread(context: Context) extends Thread {
|
||||
|
||||
val TAG = "TrafficMonitorThread"
|
||||
val PATH = "/data/data/com.github.shadowsocks/stat_path"
|
||||
lazy val PATH = context.getApplicationInfo.dataDir + "/stat_path"
|
||||
|
||||
@volatile var serverSocket: LocalServerSocket = null
|
||||
@volatile var isRunning: Boolean = true
|
||||
|
||||