diff --git a/README.md b/README.md
index a873cccd..f2ea0345 100644
--- a/README.md
+++ b/README.md
@@ -47,13 +47,13 @@ Translators can go to [POEditor](https://poeditor.com/join/project/u5VHO9vhSf) t
diff --git a/build.sbt b/build.sbt
index 1a8dceea..946d7cf2 100644
--- a/build.sbt
+++ b/build.sbt
@@ -10,6 +10,7 @@ lazy val commonSettings = Seq(
javacOptions ++= "-source" :: "1.7" :: "-target" :: "1.7" :: Nil,
scalacOptions ++= "-target:jvm-1.7" :: "-Xexperimental" :: Nil,
ndkArgs := "-j" :: java.lang.Runtime.getRuntime.availableProcessors.toString :: Nil,
+ ndkAbiFilter := Seq("armeabi-v7a", "arm64-v8a", "x86"),
proguardVersion := "5.3.3",
proguardCache := Seq(),
diff --git a/mobile/build.sbt b/mobile/build.sbt
index c15fde9d..bdb07c66 100644
--- a/mobile/build.sbt
+++ b/mobile/build.sbt
@@ -1,40 +1,57 @@
enablePlugins(AndroidApp)
+enablePlugins(AndroidGms)
+
android.useSupportVectors
name := "shadowsocks"
-version := "4.1.4"
-versionCode := Some(184)
+version := "4.1.7"
+versionCode := Some(187)
proguardOptions ++=
- "-keep class com.github.shadowsocks.JniHelper { *; }" ::
"-dontwarn com.google.android.gms.internal.**" ::
"-dontwarn com.j256.ormlite.**" ::
+ "-dontwarn okhttp3.**" ::
"-dontwarn okio.**" ::
"-dontwarn org.xbill.**" ::
+ "-keep class com.github.shadowsocks.JniHelper { *; }" ::
Nil
-val playServicesVersion = "10.2.1"
+val playServicesVersion = "10.2.6"
resolvers += Resolver.jcenterRepo
libraryDependencies ++=
"com.futuremind.recyclerfastscroll" % "fastscroll" % "0.2.5" ::
- "com.evernote" % "android-job" % "1.1.9" ::
+ "com.evernote" % "android-job" % "1.1.10" ::
"com.github.jorgecastilloprz" % "fabprogresscircle" % "1.01" ::
"com.google.android.gms" % "play-services-ads" % playServicesVersion ::
"com.google.android.gms" % "play-services-analytics" % playServicesVersion ::
"com.google.android.gms" % "play-services-gcm" % playServicesVersion ::
+ "com.google.firebase" % "firebase-config" % playServicesVersion ::
"com.j256.ormlite" % "ormlite-android" % "5.0" ::
"com.mikepenz" % "crossfader" % "1.5.0" ::
- "com.mikepenz" % "fastadapter" % "2.5.0" ::
- "com.mikepenz" % "iconics-core" % "2.8.2" ::
- "com.mikepenz" % "materialdrawer" % "5.9.0" ::
+ "com.mikepenz" % "fastadapter" % "2.5.2" ::
+ "com.mikepenz" % "iconics-core" % "2.8.4" ::
+ "com.mikepenz" % "materialdrawer" % "5.9.1" ::
"com.mikepenz" % "materialize" % "1.0.1" ::
- "com.squareup.okhttp3" % "okhttp" % "3.6.0" ::
+ "com.squareup.okhttp3" % "okhttp" % "3.8.0" ::
"com.twofortyfouram" % "android-plugin-api-for-locale" % "1.0.2" ::
"dnsjava" % "dnsjava" % "2.1.8" ::
"eu.chainfire" % "libsuperuser" % "1.0.0.201704021214" ::
"net.glxn.qrgen" % "android" % "2.0" ::
Nil
+packagingOptions := PackagingOptions(excludes =
+ "META-INF/maven/com.squareup.okio/okio/pom.properties" ::
+ "META-INF/maven/com.squareup.okio/okio/pom.xml" ::
+ "META-INF/maven/com.squareup.okhttp3/okhttp/pom.properties" ::
+ "META-INF/maven/com.squareup.okhttp3/okhttp/pom.xml" ::
+ Nil)
+
+lazy val goClean = TaskKey[Unit]("go-clean", "Clean go build dependencies")
+goClean := {
+ IO.delete(baseDirectory(base => base / "src/overture/.deps").value)
+ IO.delete(baseDirectory(base => base / "src/main/jni/overture").value)
+}
+
lazy val goBuild = TaskKey[Unit]("go-build", "Build go and overture")
goBuild := {
Process(Seq("mobile/src/overture/make.bash", minSdkVersion.value)) ! streams.value.log match {
diff --git a/mobile/google-services.json b/mobile/google-services.json
new file mode 100644
index 00000000..0fa9e0cf
--- /dev/null
+++ b/mobile/google-services.json
@@ -0,0 +1,50 @@
+{
+ "project_info": {
+ "project_number": "261400168171",
+ "firebase_url": "https://admob-app-id-3330146721.firebaseio.com",
+ "project_id": "admob-app-id-3330146721",
+ "storage_bucket": "admob-app-id-3330146721.appspot.com"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:261400168171:android:dbdd6331c434162f",
+ "android_client_info": {
+ "package_name": "com.github.shadowsocks"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "261400168171-sfik8o3pj7e243583olorh7s5974vab1.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "com.github.shadowsocks",
+ "certificate_hash": "58a90f84cfe99d4280aec677c9a1292fae131677"
+ }
+ },
+ {
+ "client_id": "261400168171-g7aelv5bu012ojr7dod7lq09c9anjimh.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyCee3fAad7nb3YsxeUO9mqqHFfAvsSCbVs"
+ }
+ ],
+ "services": {
+ "analytics_service": {
+ "status": 1
+ },
+ "appinvite_service": {
+ "status": 1,
+ "other_platform_oauth_client": []
+ },
+ "ads_service": {
+ "status": 2
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/mobile/src/main/assets/pages/about.html b/mobile/src/main/assets/pages/about.html
index fa7441fc..5020f9ef 100644
--- a/mobile/src/main/assets/pages/about.html
+++ b/mobile/src/main/assets/pages/about.html
@@ -291,13 +291,13 @@ along with this program. If not, see http
diff --git a/mobile/src/main/jni/Android.mk b/mobile/src/main/jni/Android.mk
index 90dcdf52..548fe90f 100755
--- a/mobile/src/main/jni/Android.mk
+++ b/mobile/src/main/jni/Android.mk
@@ -257,7 +257,7 @@ SHADOWSOCKS_SOURCES := local.c \
LOCAL_MODULE := ss-local
LOCAL_SRC_FILES := $(addprefix shadowsocks-libev/src/, $(SHADOWSOCKS_SOURCES))
LOCAL_CFLAGS := -Wall -O2 -fno-strict-aliasing -DMODULE_LOCAL \
- -DUSE_CRYPTO_MBEDTLS -DANDROID -DHAVE_CONFIG_H \
+ -DUSE_CRYPTO_MBEDTLS -DHAVE_CONFIG_H \
-DCONNECT_IN_PROGRESS=EINPROGRESS \
-I$(LOCAL_PATH)/include/shadowsocks-libev \
-I$(LOCAL_PATH)/include \
@@ -294,7 +294,7 @@ SHADOWSOCKS_SOURCES := tunnel.c \
LOCAL_MODULE := ss-tunnel
LOCAL_SRC_FILES := $(addprefix shadowsocks-libev/src/, $(SHADOWSOCKS_SOURCES))
LOCAL_CFLAGS := -Wall -O2 -fno-strict-aliasing -DMODULE_TUNNEL \
- -DUSE_CRYPTO_MBEDTLS -DANDROID -DHAVE_CONFIG_H -DSSTUNNEL_JNI \
+ -DUSE_CRYPTO_MBEDTLS -DHAVE_CONFIG_H -DSSTUNNEL_JNI \
-DCONNECT_IN_PROGRESS=EINPROGRESS \
-I$(LOCAL_PATH)/libancillary \
-I$(LOCAL_PATH)/include \
diff --git a/mobile/src/main/jni/badvpn b/mobile/src/main/jni/badvpn
index 057ed9f3..e5abe704 160000
--- a/mobile/src/main/jni/badvpn
+++ b/mobile/src/main/jni/badvpn
@@ -1 +1 @@
-Subproject commit 057ed9f36490a9dccd5e7337fabcb142dd3afc0d
+Subproject commit e5abe7048d5a1dea589e8e26b33e17dd9533c078
diff --git a/mobile/src/main/jni/libev b/mobile/src/main/jni/libev
index 981fb847..52134190 160000
--- a/mobile/src/main/jni/libev
+++ b/mobile/src/main/jni/libev
@@ -1 +1 @@
-Subproject commit 981fb847e1e306bc40460de4a810f63f9bbc7212
+Subproject commit 5213419011ec5de302f8bc1716f348de1fb53b12
diff --git a/mobile/src/main/jni/libevent b/mobile/src/main/jni/libevent
index 5d5914f0..359ca847 160000
--- a/mobile/src/main/jni/libevent
+++ b/mobile/src/main/jni/libevent
@@ -1 +1 @@
-Subproject commit 5d5914f00b8adefd383f66b8b352855ece22a1d7
+Subproject commit 359ca847a649b9c318f9217c0755484d98ecb779
diff --git a/mobile/src/main/jni/redsocks b/mobile/src/main/jni/redsocks
index 3bc3f03c..274334f1 160000
--- a/mobile/src/main/jni/redsocks
+++ b/mobile/src/main/jni/redsocks
@@ -1 +1 @@
-Subproject commit 3bc3f03c182b4c4ea5138eb7bebcaafe7cc0f53b
+Subproject commit 274334f14839431ae003774d99c3d1de337afff4
diff --git a/mobile/src/main/jni/shadowsocks-libev b/mobile/src/main/jni/shadowsocks-libev
index de0cebb6..72622a3e 160000
--- a/mobile/src/main/jni/shadowsocks-libev
+++ b/mobile/src/main/jni/shadowsocks-libev
@@ -1 +1 @@
-Subproject commit de0cebb62ef3b7854972f65834af7bb8aceb4bcc
+Subproject commit 72622a3e3df0d8b66f005717ecc48264275f453c
diff --git a/mobile/src/main/res/raw/gtm_default_container b/mobile/src/main/res/raw/gtm_default_container
deleted file mode 100644
index a17ed043..00000000
Binary files a/mobile/src/main/res/raw/gtm_default_container and /dev/null differ
diff --git a/mobile/src/main/res/values-ko/strings.xml b/mobile/src/main/res/values-ko/strings.xml
index 21bf407a..c7eab897 100644
--- a/mobile/src/main/res/values-ko/strings.xml
+++ b/mobile/src/main/res/values-ko/strings.xml
@@ -2,8 +2,7 @@
"켜기/끄기"
-
-"기타"
+
"프로필"
"다른 프로필로 전환하거나 새 프로필 추가"
"NAT 모드 (지원 중단)"
@@ -45,4 +44,5 @@
"루트 권한이 필요합니다"
"지원하지 않는 버전의 커널입니다: %s < 3.7.1"
"DNS 포워딩"
+"모든 DNS 요청을 외부로 포워딩 합니다"
\ No newline at end of file
diff --git a/mobile/src/main/res/values-ru/strings.xml b/mobile/src/main/res/values-ru/strings.xml
index db707e85..30d47daf 100644
--- a/mobile/src/main/res/values-ru/strings.xml
+++ b/mobile/src/main/res/values-ru/strings.xml
@@ -2,22 +2,28 @@
"Подключение"
-
-"Разное"
+
"Профиль"
"Переключить на другой профиль или добавить новые"
"Режим NAT (не рекомендуется)"
"Использовать режим NAT вместо VPN. Требует ROOT прав."
-"Отправлено: \t\t\t\t\t%3$s\t↑\t%1$s/s
+"Удалённый DNS"
+"Отправлено: \t%3$s\t↑\t%1$s/s
Получено: \t%4$s\t↓\t%2$s/s"
"
%1$s↑\t%2$s↓"
"%1$s/s↑\t%2$s/s↓"
-"Проверить подключение"
+
+- "байт"
+- "байта"
+- "байт"
+- "байт"
+
+"Проверить соединение"
"Проверка…"
-"Успешно: %dms задержка"
-"Сбой проверки интернет подключения: %s"
-"Интернет Недоступен"
+"Успешно: задержка %d мс"
+"Сбой проверки интернет-соединения: %s"
+"Интернет недоступен"
"Код ошибки: #%d"
@@ -30,7 +36,7 @@
"IPv6 Маршрут"
-"Перенаправлять IPv6 траффик на удалённый сервер"
+"Перенаправлять трафик IPv6 на удалённый сервер"
"Маршрут"
"Список GFW"
"Прокси для выбранных приложений"
@@ -42,22 +48,23 @@
"Запускать Shadowsocks при включении"
"Переключение требует наличия ROOT прав"
"Неподдерживаемая версия ядра: %s < 3.7.1"
-"Проброс DNS"
-"Пробрасывать DNS пакеты на удалённый сервер"
+"Перенаправление DNS"
+"Перенаправлять все DNS-запросы на удалённый сервер"
"Shadowsocks запущен."
"Неправильное имя сервера"
"Ошибка при подключении к удалённому серверу"
-"ВНИМАНИЕ:режим NAT не работает в Android 5.0"
+"ВНИМАНИЕ: режим NAT не рекомендуется, начиная с Android 5.0"
"Режим NAT требует наличия ROOT прав"
"Переключить на режим VPN"
"Остановить"
"Останавливается…"
-"Сбой запуска VPN сервиса. Требуется перезагрузка Вашего устройства."
+"Не удалось запустить службу VPN. Возможно, требуется перезагрузить ваше устройство."
"Закрыть"
+"Пожалуйста, выберите профиль"
"Прокси/Пароль не должны быть пустыми"
"Подключить"
"Сброс…"
@@ -69,6 +76,7 @@
"Сброс"
"О приложении"
"Shadowsocks %s"
+"Изменить"
"Поделиться"
"Добавить Профиль"
"Применить настройки для всех профилей"
@@ -78,19 +86,26 @@
"Сбой экспорта."
"Успешный импорт!"
"Сбой импорта."
+
+
+"Настройка профиля"
+"Удалить"
+"Вы уверены, что хотите удалить этот профиль?"
+"QR-код/NFC"
"Добавить этот Профиль Shadowsocks?"
-"Сканировать QR код"
-"Настройка вручную"
+"Сканировать QR-код"
+"Ручные настройки"
+"Пожалуйста, установите любое ZXing-совместимое приложение для сканирования QR-кодов."
-- "Удалён"
-- "%d элементы удалены"
-- "%d элементы удалены"
-- "%d элементы удалены"
+- "Удалено"
+- "Удалено %d элемента"
+- "Удалено %d элементов"
+- "Удалено %d элементов"
"Вернуть"
-"Запустить сервисStart the service"
+"Запустить службу"
"Подключиться к текущему серверу"
"Подключиться к %s"
"Переключить на %s"
@@ -99,10 +114,30 @@
"Отправлено:"
"Получено:"
+"Соединение..."
+"Подключено, нажмите для проверки соединения"
+"Подключено"
+"Не подключено"
+
+
+"Пользовательские правила"
+"Выделение..."
+"Добавить правило..."
+"Редактировать правило"
"Все"
-"Обход LAN"
-"Обходной Китай"
-"Обход LAN и Китай"
+"Все, кроме LAN"
+"Все, кроме Китая"
+"Все, кроме LAN и Китая"
"Список Китай"
"Установить прокси для выбранных приложений"
+"Подсеть/Регулярное выражение (PCRE) имени хоста"
+"Доменное имя и все его поддомены"
+
+
+"Плагин"
+"Настроить..."
+"Отключён"
+"Неизвестный плагин %s"
+"Предупреждение: этот плагин получен из недоверенного источника."
+"Плагин: %s"
\ No newline at end of file
diff --git a/mobile/src/main/res/values-zh-rTW/strings.xml b/mobile/src/main/res/values-zh-rTW/strings.xml
index e7c8c5bc..9e01852e 100644
--- a/mobile/src/main/res/values-zh-rTW/strings.xml
+++ b/mobile/src/main/res/values-zh-rTW/strings.xml
@@ -2,8 +2,7 @@
"切換"
-
-"其他"
+
"設定檔"
"切換至其他設定檔或新增新設定檔"
"NAT 模式 (已過時)"
@@ -124,4 +123,12 @@
"為已選擇的應用程式設定 Proxy"
"子網路/主機名稱 PCRE 模式"
"網域及其所有子網域"
-
\ No newline at end of file
+
+
+"插件"
+"配置..."
+"未啟用"
+"未知插件 %s"
+"警告:該插件似乎不是來自一個已知的可信任源。"
+"插件: %s"
+
diff --git a/mobile/src/main/res/xml/default_configs.xml b/mobile/src/main/res/xml/default_configs.xml
new file mode 100644
index 00000000..2f71ea5e
--- /dev/null
+++ b/mobile/src/main/res/xml/default_configs.xml
@@ -0,0 +1,7 @@
+
+
+
+ proxy_url
+ https://www.socks123.pw/get.php
+
+
diff --git a/mobile/src/main/scala/com/github/shadowsocks/BaseService.scala b/mobile/src/main/scala/com/github/shadowsocks/BaseService.scala
index e84e7a6a..b9a8ac02 100644
--- a/mobile/src/main/scala/com/github/shadowsocks/BaseService.scala
+++ b/mobile/src/main/scala/com/github/shadowsocks/BaseService.scala
@@ -21,7 +21,6 @@
package com.github.shadowsocks
import java.io.{File, IOException}
-import java.net.InetAddress
import java.util
import java.util.concurrent.TimeUnit
import java.util.{Timer, TimerTask}
@@ -127,12 +126,8 @@ trait BaseService extends Service {
def connect() {
profile.name = profile.getName // save original name before it's (possibly) overwritten by IP addresses
- if (profile.host == "198.199.101.152") {
- val holder = app.containerHolder
- val container = holder.getContainer
- val url = container.getString("proxy_url")
- val sig = Utils.getSignature(this)
+ if (profile.host == "198.199.101.152") {
val client = new OkHttpClient.Builder()
.dns(hostname => Utils.resolve(hostname, enableIPv6 = false) match {
case Some(ip) => util.Arrays.asList(InetAddress.getByName(ip))
@@ -143,10 +138,10 @@ trait BaseService extends Service {
.readTimeout(30, TimeUnit.SECONDS)
.build()
val requestBody = new FormBody.Builder()
- .add("sig", sig)
+ .add("sig", Utils.getSignature(this))
.build()
val request = new Request.Builder()
- .url(url)
+ .url(app.remoteConfig.getString("proxy_url"))
.post(requestBody)
.build()
@@ -277,7 +272,6 @@ trait BaseService extends Service {
override def onCreate() {
super.onCreate()
- app.refreshContainerHolder()
app.updateAssets()
}
@@ -302,23 +296,12 @@ trait BaseService extends Service {
}
}
- def getBlackList: String = {
- val default = getString(R.string.black_list)
- try {
- val container = app.containerHolder.getContainer
- val update = container.getString("black_list_lite")
- val list = if (update == null || update.isEmpty) default else update
- "exclude = " + list + ";"
- } catch {
- case _: Exception => "exclude = " + default + ";"
- }
- }
-
protected def buildPluginCommandLine(): ArrayBuffer[String] = {
val result = ArrayBuffer(pluginPath)
if (TcpFastOpen.sendEnabled) result += "--fast-open"
result
}
+
protected final def buildShadowsocksConfig(file: String): String = {
val config = new JSONObject()
.put("server", profile.host)
@@ -332,16 +315,9 @@ trait BaseService extends Service {
file
}
- private final def buildRemoteDns(remoteDns: String): String = {
- val addr = InetAddress.getByName(remoteDns)
- if (addr.isInstanceOf[Inet6Address])
- return "[" + remoteDns + "]"
- remoteDns
- }
-
protected final def buildOvertureConfig(file: String): String = {
val config = new JSONObject()
- .put("BindAddress", ":" + (profile.localPort + 53))
+ .put("BindAddress", "127.0.0.1:" + (profile.localPort + 53))
.put("RedirectIPv6Record", true)
.put("DomainBase64Decode", true)
.put("HostsFile", "hosts")
@@ -350,7 +326,10 @@ trait BaseService extends Service {
def makeDns(name: String, address: String, edns: Boolean = true) = {
val dns = new JSONObject()
.put("Name", name)
- .put("Address", address + ":53")
+ .put("Address", (Utils.parseNumericAddress(address) match {
+ case _: Inet6Address => '[' + address + ']'
+ case _ => address
+ }) + ":53")
.put("Timeout", 6)
.put("EDNSClientSubnet", new JSONObject().put("Policy", "disable"))
if (edns) dns
@@ -359,24 +338,25 @@ trait BaseService extends Service {
else dns.put("Protocol", "udp")
dns
}
+ val remoteDns = new JSONArray(profile.remoteDns.split(",").zipWithIndex.map {
+ case (dns, i) => makeDns("UserDef-" + i, dns.trim)
+ })
profile.route match {
case Acl.BYPASS_CHN | Acl.BYPASS_LAN_CHN | Acl.GFWLIST | Acl.CUSTOM_RULES => config
.put("PrimaryDNS", new JSONArray(Array(
makeDns("Primary-1", "119.29.29.29", edns = false),
makeDns("Primary-2", "114.114.114.114", edns = false)
)))
- .put("AlternativeDNS", new JSONArray().put(makeDns("Alternative",
- buildRemoteDns(profile.remoteDns.trim))))
+ .put("AlternativeDNS", remoteDns)
.put("IPNetworkFile", "china_ip_list.txt")
.put("DomainFile", "gfwlist.txt")
case Acl.CHINALIST => config
.put("PrimaryDNS", new JSONArray().put(makeDns("Primary", "119.29.29.29")))
- .put("AlternativeDNS", new JSONArray().put(makeDns("Alternative",
- buildRemoteDns(profile.remoteDns.trim))))
+ .put("AlternativeDNS", remoteDns)
case _ => config
- .put("PrimaryDNS", new JSONArray().put(makeDns("Primary",
- buildRemoteDns(profile.remoteDns.trim))))
- .put("AlternativeDNS", new JSONArray().put(makeDns("Alternative", "208.67.222.222")))
+ .put("PrimaryDNS", remoteDns)
+ // no need to setup AlternativeDNS in Acl.ALL/BYPASS_LAN mode
+ .put("OnlyPrimaryDNS", true)
}
IOUtils.writeString(new File(getFilesDir, file), config.toString)
file
diff --git a/mobile/src/main/scala/com/github/shadowsocks/GuardedProcess.scala b/mobile/src/main/scala/com/github/shadowsocks/GuardedProcess.scala
index bdd6cd7c..5953d372 100644
--- a/mobile/src/main/scala/com/github/shadowsocks/GuardedProcess.scala
+++ b/mobile/src/main/scala/com/github/shadowsocks/GuardedProcess.scala
@@ -33,9 +33,9 @@ import com.github.shadowsocks.ShadowsocksApplication.app
import scala.collection.JavaConversions._
import scala.collection.immutable.Stream
-class StreamLogger(is: InputStream, tag: String) extends Thread {
+class StreamLogger(is: InputStream, tag: String, logger: (String, String) => Int) extends Thread {
override def run(): Unit = autoClose(new BufferedReader(new InputStreamReader(is)))(br =>
- try Stream.continually(br.readLine()).takeWhile(_ != null).foreach(Log.i(tag, _)) catch {
+ try Stream.continually(br.readLine()).takeWhile(_ != null).foreach(logger(tag, _)) catch {
case _: IOException =>
})
}
@@ -68,8 +68,8 @@ class GuardedProcess(cmd: String*) {
.directory(app.getFilesDir)
.start()
- val is = process.getInputStream
- new StreamLogger(is, TAG).start()
+ new StreamLogger(process.getInputStream(), TAG, Log.i).start()
+ new StreamLogger(process.getErrorStream(), TAG, Log.e).start()
if (callback == null) callback = onRestartCallback else callback()
diff --git a/mobile/src/main/scala/com/github/shadowsocks/MainActivity.scala b/mobile/src/main/scala/com/github/shadowsocks/MainActivity.scala
index 01ca9687..61211364 100644
--- a/mobile/src/main/scala/com/github/shadowsocks/MainActivity.scala
+++ b/mobile/src/main/scala/com/github/shadowsocks/MainActivity.scala
@@ -390,7 +390,7 @@ class MainActivity extends Activity with ServiceBoundContext with Drawer.OnDrawe
protected override def onResume() {
super.onResume()
- app.refreshContainerHolder()
+ app.remoteConfig.fetch()
state match {
case State.STOPPING | State.CONNECTING =>
case _ => hideCircle()
diff --git a/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala b/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala
index 4b533e85..96840c4b 100644
--- a/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala
+++ b/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala
@@ -21,9 +21,7 @@
package com.github.shadowsocks
import java.io.{File, FileOutputStream, IOException}
-import java.util
import java.util.Locale
-import java.util.concurrent.TimeUnit
import android.annotation.SuppressLint
import android.app.Application
@@ -39,8 +37,8 @@ import com.github.shadowsocks.database.{DBHelper, Profile, ProfileManager}
import com.github.shadowsocks.utils.CloseUtils._
import com.github.shadowsocks.utils._
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.google.firebase.FirebaseApp
+import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import com.j256.ormlite.logger.LocalLog
import eu.chainfire.libsuperuser.Shell
@@ -61,8 +59,7 @@ object ShadowsocksApplication {
class ShadowsocksApplication extends Application {
import ShadowsocksApplication._
- final val SIG_FUNC = "getSignature"
- var containerHolder: ContainerHolder = _
+ lazy val remoteConfig = FirebaseRemoteConfig.getInstance()
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
@@ -149,35 +146,16 @@ class ShadowsocksApplication extends Application {
if (!BuildConfig.DEBUG) java.lang.System.setProperty(LocalLog.LOCAL_LOG_LEVEL_PROPERTY, "ERROR")
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
checkChineseLocale(getResources.getConfiguration)
- val tm = TagManager.getInstance(this)
- val pending = tm.loadContainerPreferNonDefault("GTM-NT8WS8", R.raw.gtm_default_container)
- val callback = new ResultCallback[ContainerHolder] {
- override def onResult(holder: ContainerHolder) {
- if (!holder.getStatus.isSuccess) {
- return
- }
- containerHolder = holder
- val container = holder.getContainer
- container.registerFunctionCallMacroCallback(SIG_FUNC,
- (functionName: String, parameters: util.Map[String, AnyRef]) => {
- if (functionName == SIG_FUNC) {
- Utils.getSignature(getApplicationContext)
- }
- null
- })
- }
- }
- pending.setResultCallback(callback, 2, TimeUnit.SECONDS)
+
+ FirebaseApp.initializeApp(this)
+ remoteConfig.setDefaults(R.xml.default_configs)
+ remoteConfig.fetch().addOnCompleteListener(task => if (task.isSuccessful) remoteConfig.activateFetched())
+
JobManager.create(this).addJobCreator(DonaldTrump)
TcpFastOpen.enabled(settings.getBoolean(Key.tfo, TcpFastOpen.sendEnabled))
}
- def refreshContainerHolder() {
- val holder = app.containerHolder
- if (holder != null) holder.refresh()
- }
-
def crashRecovery() {
val cmd = new ArrayBuffer[String]()
diff --git a/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala b/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala
index ef105f73..d5855834 100644
--- a/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala
+++ b/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala
@@ -74,7 +74,7 @@ class ShadowsocksNatService extends BaseService {
"-t", "10",
"-b", "127.0.0.1",
"-l", (profile.localPort + 63).toString,
- "-L", profile.remoteDns.trim + ":53",
+ "-L", profile.remoteDns.split(",").head.trim + ":53",
"-c", buildShadowsocksConfig("ss-tunnel-nat.conf"))
if (profile.udpdns) cmd.append("-u")
diff --git a/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala b/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala
index 8812c447..81ac83ee 100644
--- a/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala
+++ b/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala
@@ -22,8 +22,6 @@ package com.github.shadowsocks
import java.io.File
import java.util.Locale
-import java.net.InetAddress
-import java.net.Inet6Address
import android.content._
import android.content.pm.PackageManager.NameNotFoundException
@@ -145,7 +143,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
/** Called when the activity is first created. */
def handleConnection() {
-
+
startShadowsocksDaemon()
if (!profile.udpdns) {
@@ -216,18 +214,17 @@ class ShadowsocksVpnService extends VpnService with BaseService {
}
}
- if (profile.route == Acl.ALL || profile.route == Acl.BYPASS_CHN) {
+ if (profile.route == Acl.ALL
+ || profile.route == Acl.BYPASS_CHN
+ || profile.route == Acl.CUSTOM_RULES) {
builder.addRoute("0.0.0.0", 0)
} else {
getResources.getStringArray(R.array.bypass_private_route).foreach(cidr => {
val subnet = Subnet.fromString(cidr)
builder.addRoute(subnet.address.getHostAddress, subnet.prefixSize)
})
- val addr = InetAddress.getByName(profile.remoteDns.trim)
- if (addr.isInstanceOf[Inet6Address])
- builder.addRoute(addr, 128)
- else if (addr.isInstanceOf[InetAddress])
- builder.addRoute(addr, 32)
+ profile.remoteDns.split(",").map(dns => Utils.parseNumericAddress(dns.trim)).foreach(dns =>
+ builder.addRoute(dns, dns.getAddress.length << 3))
}
conn = builder.establish()
@@ -250,7 +247,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
cmd += "--enable-udprelay"
if (!profile.udpdns)
- cmd += ("--dnsgw", "%s:%d".formatLocal(Locale.ENGLISH, PRIVATE_VLAN.formatLocal(Locale.ENGLISH, "1"),
+ cmd += ("--dnsgw", "%s:%d".formatLocal(Locale.ENGLISH, "127.0.0.1",
profile.localPort + 53))
tun2socksProcess = new GuardedProcess(cmd: _*).start(() => sendFd(fd))
diff --git a/mobile/src/main/scala/com/github/shadowsocks/acl/AclSyncJob.scala b/mobile/src/main/scala/com/github/shadowsocks/acl/AclSyncJob.scala
index 54129aef..c532039c 100644
--- a/mobile/src/main/scala/com/github/shadowsocks/acl/AclSyncJob.scala
+++ b/mobile/src/main/scala/com/github/shadowsocks/acl/AclSyncJob.scala
@@ -34,6 +34,7 @@ import scala.io.Source
*/
object AclSyncJob {
final val TAG = "AclSyncJob"
+ final val MAX_RESCHEDULE = 3
def schedule(route: String): Int = new JobRequest.Builder(AclSyncJob.TAG + ':' + route)
.setExecutionWindow(TimeUnit.SECONDS.toMillis(10), TimeUnit.DAYS.toMillis(28))
@@ -54,7 +55,7 @@ class AclSyncJob(route: String) extends Job {
} catch {
case e: IOException =>
e.printStackTrace()
- Result.RESCHEDULE
+ if (params.getFailureCount < AclSyncJob.MAX_RESCHEDULE) Result.RESCHEDULE else Result.FAILURE
case e: Exception => // unknown failures, probably shouldn't retry
e.printStackTrace()
Result.FAILURE
diff --git a/mobile/src/main/scala/com/github/shadowsocks/utils/Utils.scala b/mobile/src/main/scala/com/github/shadowsocks/utils/Utils.scala
index a97f6f25..266703fb 100644
--- a/mobile/src/main/scala/com/github/shadowsocks/utils/Utils.scala
+++ b/mobile/src/main/scala/com/github/shadowsocks/utils/Utils.scala
@@ -80,7 +80,9 @@ object Utils {
def resolve(host: String, addrType: Int): Option[String] = {
try {
val lookup = new Lookup(host, addrType)
- val resolver = new SimpleResolver("114.114.114.114")
+ val resolver = new SimpleResolver("208.67.220.220")
+ resolver.setTCP(true)
+ resolver.setPort(443)
resolver.setTimeout(5)
lookup.setResolver(resolver)
val result = lookup.run()
diff --git a/mobile/src/overture/go b/mobile/src/overture/go
index 86036dcc..26db64c7 160000
--- a/mobile/src/overture/go
+++ b/mobile/src/overture/go
@@ -1 +1 @@
-Subproject commit 86036dcce8fc7e2bd772969e6af56776cc9d8d53
+Subproject commit 26db64c76604b35e756f593d8ce25da5a83af6b6
diff --git a/mobile/src/overture/make.bash b/mobile/src/overture/make.bash
index bf008d15..36242a77 100755
--- a/mobile/src/overture/make.bash
+++ b/mobile/src/overture/make.bash
@@ -4,7 +4,7 @@ function try () {
"$@" || exit -1
}
-[ -z "$ANDROID_NDK_HOME" ] && ANDROID_NDK_HOME=~/android-ndk-r12b
+[ -z "$ANDROID_NDK_HOME" ] && ANDROID_NDK_HOME=$ANDROID_HOME/ndk-bundle
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
MIN_API=$1
@@ -15,13 +15,13 @@ ANDROID_ARM_TOOLCHAIN=$DEPS/android-toolchain-${MIN_API}-arm
ANDROID_ARM64_TOOLCHAIN=$DEPS/android-toolchain-21-arm64
ANDROID_X86_TOOLCHAIN=$DEPS/android-toolchain-${MIN_API}-x86
-ANDROID_ARM_CC=$ANDROID_ARM_TOOLCHAIN/bin/arm-linux-androideabi-gcc
+ANDROID_ARM_CC=$ANDROID_ARM_TOOLCHAIN/bin/arm-linux-androideabi-clang
ANDROID_ARM_STRIP=$ANDROID_ARM_TOOLCHAIN/bin/arm-linux-androideabi-strip
-ANDROID_ARM64_CC=$ANDROID_ARM64_TOOLCHAIN/bin/aarch64-linux-android-gcc
+ANDROID_ARM64_CC=$ANDROID_ARM64_TOOLCHAIN/bin/aarch64-linux-android-clang
ANDROID_ARM64_STRIP=$ANDROID_ARM64_TOOLCHAIN/bin/aarch64-linux-android-strip
-ANDROID_X86_CC=$ANDROID_X86_TOOLCHAIN/bin/i686-linux-android-gcc
+ANDROID_X86_CC=$ANDROID_X86_TOOLCHAIN/bin/i686-linux-android-clang
ANDROID_X86_STRIP=$ANDROID_X86_TOOLCHAIN/bin/i686-linux-android-strip
try mkdir -p $DEPS $TARGET/armeabi-v7a $TARGET/x86 $TARGET/arm64-v8a
diff --git a/mobile/src/overture/src/github.com/shadowsocks/overture b/mobile/src/overture/src/github.com/shadowsocks/overture
index 7263b82d..943e9dcb 160000
--- a/mobile/src/overture/src/github.com/shadowsocks/overture
+++ b/mobile/src/overture/src/github.com/shadowsocks/overture
@@ -1 +1 @@
-Subproject commit 7263b82d2eba2e28d70766aed36ffbc7cf0e1451
+Subproject commit 943e9dcb62c47e9016b39185c4d92592e05b6fbb
diff --git a/plugin/src/main/res/values-ru/strings.xml b/plugin/src/main/res/values-ru/strings.xml
index 12b5ce91..0e708a6e 100644
--- a/plugin/src/main/res/values-ru/strings.xml
+++ b/plugin/src/main/res/values-ru/strings.xml
@@ -6,4 +6,10 @@
"Дополнительные Настройки"
+
+
+"Да"
+"Нет"
+"Изменения не сохранены. Сохранить?"
+"Применить"
\ No newline at end of file
diff --git a/project/plugins.sbt b/project/plugins.sbt
index 2bf0931c..8fd06146 100644
--- a/project/plugins.sbt
+++ b/project/plugins.sbt
@@ -7,3 +7,5 @@ addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.8.2")
addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "1.1")
addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.0") // fot sbt-0.13.5 or higher
+
+addSbtPlugin("org.scala-android" % "sbt-android-gms" % "0.4")