Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9fa4481a2 | ||
|
|
e2c29594f2 | ||
|
|
2ef042d56b | ||
|
|
0fa97f064f | ||
|
|
d7ecc34836 | ||
|
|
168c0588a6 | ||
|
|
4f5ee68f40 | ||
|
|
0c3352935a | ||
|
|
0d02a39b61 | ||
|
|
090cc35bff | ||
|
|
042ee55421 | ||
|
|
ac96e6fc9c | ||
|
|
c6ff9b3d89 | ||
|
|
77af5f6e3c | ||
|
|
95db29bd13 | ||
|
|
7297a2664c | ||
|
|
195e2afbeb | ||
|
|
3dbc5f4147 | ||
|
|
580ce14809 | ||
|
|
d4213e8ee8 | ||
|
|
be168c77f6 | ||
|
|
f9b29acd82 | ||
|
|
4e943bc782 | ||
|
|
b3a818b03a | ||
|
|
982845e877 | ||
|
|
4e35fe19c8 | ||
|
|
45d8e827c1 | ||
|
|
90dd0ab300 | ||
|
|
dee540b83a | ||
|
|
f3b3507c0f | ||
|
|
402710841b | ||
|
|
cd1f94f4a0 | ||
|
|
6dace959d2 |
@@ -34,10 +34,10 @@
|
|||||||
3. Если вы используете фреймворк Xposed и/или приложения для энергосбережения, вероятно наше приложение не будет нормально работать с ними.
|
3. Если вы используете фреймворк Xposed и/или приложения для энергосбережения, вероятно наше приложение не будет нормально работать с ними.
|
||||||
|
|
||||||
* Иправления для MIUI: [#772](https://github.com/shadowsocks/shadowsocks-android/issues/772)
|
* Иправления для MIUI: [#772](https://github.com/shadowsocks/shadowsocks-android/issues/772)
|
||||||
* Иправления для Huawei: [#1091 (comment)](https://github.com/shadowsocks/shadowsocks-android/issues/1091#issuecomment-276949836)
|
* Иправления для Huawei: [#1091 (комментарий)](https://github.com/shadowsocks/shadowsocks-android/issues/1091#issuecomment-276949836)
|
||||||
* Вызванные из-за Xposed: [#1414](https://github.com/shadowsocks/shadowsocks-android/issues/1414)
|
* Вызванные из-за Xposed: [#1414](https://github.com/shadowsocks/shadowsocks-android/issues/1414)
|
||||||
* Samsung и/или Brevent: [#1410](https://github.com/shadowsocks/shadowsocks-android/issues/1410)
|
* Samsung и/или Brevent: [#1410](https://github.com/shadowsocks/shadowsocks-android/issues/1410)
|
||||||
* Не устанавливайте это приложение на SD карту, из-за проблем с разрешениями: [#1124 (comment)](https://github.com/shadowsocks/shadowsocks-android/issues/1124#issuecomment-307556453)
|
* Не устанавливайте это приложение на SD карту, из-за проблем с разрешениями: [#1124 (комментарий)](https://github.com/shadowsocks/shadowsocks-android/issues/1124#issuecomment-307556453)
|
||||||
|
|
||||||
### Как приостановить службу Shadowsocks?
|
### Как приостановить службу Shadowsocks?
|
||||||
|
|
||||||
@@ -55,7 +55,9 @@
|
|||||||
|
|
||||||
### Оно прекрасно работает при Wi-Fi но не может подключиться через сотовую связь?
|
### Оно прекрасно работает при Wi-Fi но не может подключиться через сотовую связь?
|
||||||
|
|
||||||
Разрешите этому app to consume background data in app settings.
|
Разрешите этому приложению передачу данных в фоновом режиме в настройках приложения.
|
||||||
|
|
||||||
|
Если у вас оперератор Yota, то измените точку доступа APN с `yota.ru` на `client.yota.ru`
|
||||||
|
|
||||||
### Почему требуется разрешение камере на устройствах младше Android 6.0?
|
### Почему требуется разрешение камере на устройствах младше Android 6.0?
|
||||||
|
|
||||||
|
|||||||
@@ -24,3 +24,6 @@ core/src/overture/src/gopkg.in
|
|||||||
# work in progress
|
# work in progress
|
||||||
tv/
|
tv/
|
||||||
things/
|
things/
|
||||||
|
|
||||||
|
# release apks
|
||||||
|
*.apk
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
## Shadowsocks for Android
|
## Shadowsocks for Android
|
||||||
|
|
||||||
[](https://travis-ci.org/shadowsocks/shadowsocks-android)
|
[](https://travis-ci.org/shadowsocks/shadowsocks-android)
|
||||||
|
[](https://android-arsenal.com/api?level=21)
|
||||||
[](https://github.com/shadowsocks/shadowsocks-android/releases)
|
[](https://github.com/shadowsocks/shadowsocks-android/releases)
|
||||||
|
[](https://www.gnu.org/licenses/gpl-3.0)
|
||||||
|
|
||||||
A [shadowsocks](http://shadowsocks.org) client for Android, written in Kotlin.
|
A [shadowsocks](http://shadowsocks.org) client for Android, written in Kotlin.
|
||||||
<a href="https://play.google.com/store/apps/details?id=com.github.shadowsocks"><img src="https://play.google.com/intl/en_us/badges/images/generic/en-play-badge.png" height="48"></a>
|
<a href="https://play.google.com/store/apps/details?id=com.github.shadowsocks"><img src="https://play.google.com/intl/en_us/badges/images/generic/en-play-badge.png" height="48"></a>
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext {
|
ext {
|
||||||
kotlinVersion = '1.2.10'
|
kotlinVersion = '1.2.20'
|
||||||
minSdkVersion = 19
|
minSdkVersion = 21
|
||||||
sdkVersion = 27
|
sdkVersion = 27
|
||||||
buildToolsVersion = '27.0.3'
|
buildToolsVersion = '27.0.3'
|
||||||
supportLibraryVersion = '27.0.2'
|
supportLibraryVersion = '27.0.2'
|
||||||
|
|||||||
@@ -36,19 +36,28 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
task goBuild(type: Exec) {
|
task goBuild(type: Exec) {
|
||||||
executable "sh"
|
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
||||||
args "-c", "src/overture/make.bash " + minSdkVersion
|
executable "cmd.exe"
|
||||||
|
args "/c", "src\\overture\\make.bat " + minSdkVersion
|
||||||
|
} else {
|
||||||
|
executable "sh"
|
||||||
|
args "-c", "src/overture/make.bash " + minSdkVersion
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task goClean(type: Exec) {
|
task goClean(type: Exec) {
|
||||||
executable "sh"
|
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
||||||
args "-c", "src/overture/clean.bash"
|
executable "cmd.exe"
|
||||||
|
args "/c", "src\\overture\\clean.bat"
|
||||||
|
} else {
|
||||||
|
executable "sh"
|
||||||
|
args "-c", "src/overture/clean.bash"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.whenTaskAdded { task ->
|
tasks.whenTaskAdded { task ->
|
||||||
if ((task.name == 'generateJsonModelDebug' ||
|
if ((task.name == 'generateJsonModelDebug' ||
|
||||||
task.name == 'generateJsonModelRelease') &&
|
task.name == 'generateJsonModelRelease')) {
|
||||||
!Os.isFamily(Os.FAMILY_WINDOWS)) {
|
|
||||||
task.dependsOn(goBuild)
|
task.dependsOn(goBuild)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,8 +43,6 @@ import android.support.annotation.NonNull;
|
|||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.system.ErrnoException;
|
import android.system.ErrnoException;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
|
||||||
|
|
||||||
public class JniHelper {
|
public class JniHelper {
|
||||||
static {
|
static {
|
||||||
System.loadLibrary("jni-helper");
|
System.loadLibrary("jni-helper");
|
||||||
@@ -54,8 +52,7 @@ public class JniHelper {
|
|||||||
public static void sigtermCompat(@NonNull Process process) throws Exception {
|
public static void sigtermCompat(@NonNull Process process) throws Exception {
|
||||||
if (Build.VERSION.SDK_INT >= 24) throw new UnsupportedOperationException("Never call this method in OpenJDK!");
|
if (Build.VERSION.SDK_INT >= 24) throw new UnsupportedOperationException("Never call this method in OpenJDK!");
|
||||||
int errno = sigterm(process);
|
int errno = sigterm(process);
|
||||||
if (errno != 0) throw Build.VERSION.SDK_INT >= 21
|
if (errno != 0) throw new ErrnoException("kill", errno);
|
||||||
? new ErrnoException("kill", errno) : new Exception("kill failed: " + errno);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated // only implemented for before API 24
|
@Deprecated // only implemented for before API 24
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
APP_ABI := armeabi-v7a arm64-v8a x86
|
APP_ABI := armeabi-v7a arm64-v8a x86
|
||||||
APP_PLATFORM := android-19
|
APP_PLATFORM := android-21
|
||||||
APP_STL := c++_static
|
APP_STL := c++_static
|
||||||
NDK_TOOLCHAIN_VERSION := clang
|
NDK_TOOLCHAIN_VERSION := clang
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
# executable program
|
# executable program
|
||||||
#
|
#
|
||||||
# Modified by @Mygod, based on:
|
# Modified by @Mygod, based on:
|
||||||
# https://android.googlesource.com/platform/ndk/+/f2e98f8c066aed59caf61163d4b87c2b858f9814/build/core/build-shared-library.mk
|
# https://android.googlesource.com/platform/ndk/+/a355a4e/build/core/build-shared-library.mk
|
||||||
# https://android.googlesource.com/platform/ndk/+/f2e98f8c066aed59caf61163d4b87c2b858f9814/build/core/build-executable.mk
|
# https://android.googlesource.com/platform/ndk/+/a355a4e/build/core/build-executable.mk
|
||||||
LOCAL_BUILD_SCRIPT := BUILD_EXECUTABLE
|
LOCAL_BUILD_SCRIPT := BUILD_EXECUTABLE
|
||||||
LOCAL_MAKEFILE := $(local-makefile)
|
LOCAL_MAKEFILE := $(local-makefile)
|
||||||
$(call check-defined-LOCAL_MODULE,$(LOCAL_BUILD_SCRIPT))
|
$(call check-defined-LOCAL_MODULE,$(LOCAL_BUILD_SCRIPT))
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
@ECHO OFF
|
||||||
|
|
||||||
|
SET DIR=%~dp0
|
||||||
|
SET DEPS=%DIR%\.deps
|
||||||
|
|
||||||
|
RD /S /Q %DEPS%
|
||||||
|
RD /S /Q %DIR%\go\bin
|
||||||
|
RD /S /Q %DIR%\bin
|
||||||
|
|
||||||
|
ECHO "Successfully clean overture"
|
||||||
@@ -12,7 +12,7 @@ TARGET=$DIR/bin
|
|||||||
DEPS=$DIR/.deps
|
DEPS=$DIR/.deps
|
||||||
|
|
||||||
ANDROID_ARM_TOOLCHAIN=$DEPS/android-toolchain-${MIN_API}-arm
|
ANDROID_ARM_TOOLCHAIN=$DEPS/android-toolchain-${MIN_API}-arm
|
||||||
ANDROID_ARM64_TOOLCHAIN=$DEPS/android-toolchain-21-arm64
|
ANDROID_ARM64_TOOLCHAIN=$DEPS/android-toolchain-${MIN_API}-arm64
|
||||||
ANDROID_X86_TOOLCHAIN=$DEPS/android-toolchain-${MIN_API}-x86
|
ANDROID_X86_TOOLCHAIN=$DEPS/android-toolchain-${MIN_API}-x86
|
||||||
|
|
||||||
ANDROID_ARM_CC=$ANDROID_ARM_TOOLCHAIN/bin/arm-linux-androideabi-clang
|
ANDROID_ARM_CC=$ANDROID_ARM_TOOLCHAIN/bin/arm-linux-androideabi-clang
|
||||||
@@ -35,7 +35,7 @@ fi
|
|||||||
if [ ! -f "$ANDROID_ARM64_CC" ]; then
|
if [ ! -f "$ANDROID_ARM64_CC" ]; then
|
||||||
echo "Make standalone toolchain for ARM64 arch"
|
echo "Make standalone toolchain for ARM64 arch"
|
||||||
$ANDROID_NDK_HOME/build/tools/make_standalone_toolchain.py --arch arm64 \
|
$ANDROID_NDK_HOME/build/tools/make_standalone_toolchain.py --arch arm64 \
|
||||||
--api 21 --install-dir $ANDROID_ARM64_TOOLCHAIN
|
--api $MIN_API --install-dir $ANDROID_ARM64_TOOLCHAIN
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -f "$ANDROID_X86_CC" ]; then
|
if [ ! -f "$ANDROID_X86_CC" ]; then
|
||||||
|
|||||||
@@ -0,0 +1,121 @@
|
|||||||
|
@ECHO OFF
|
||||||
|
SETLOCAL
|
||||||
|
|
||||||
|
IF NOT DEFINED ANDROID_NDK_HOME (
|
||||||
|
SET ANDROID_NDK_HOME=%ANDROID_HOME%\ndk-bundle
|
||||||
|
)
|
||||||
|
|
||||||
|
SET DIR=%~dp0
|
||||||
|
SET MIN_API=%1%
|
||||||
|
SET TARGET=%DIR%\bin
|
||||||
|
SET DEPS=%DIR%\.deps
|
||||||
|
|
||||||
|
SET ANDROID_ARM_TOOLCHAIN=%DEPS%\android-toolchain-%MIN_API%-arm
|
||||||
|
SET ANDROID_ARM64_TOOLCHAIN=%DEPS%\android-toolchain-%MIN_API%-arm64
|
||||||
|
SET ANDROID_X86_TOOLCHAIN=%DEPS%\android-toolchain-%MIN_API%-x86
|
||||||
|
|
||||||
|
SET ANDROID_ARM_CC=%ANDROID_ARM_TOOLCHAIN%\bin\arm-linux-androideabi-clang
|
||||||
|
SET ANDROID_ARM_STRIP=%ANDROID_ARM_TOOLCHAIN%\bin\arm-linux-androideabi-strip
|
||||||
|
|
||||||
|
SET ANDROID_ARM64_CC=%ANDROID_ARM64_TOOLCHAIN%\bin\aarch64-linux-android-clang
|
||||||
|
SET ANDROID_ARM64_STRIP=%ANDROID_ARM64_TOOLCHAIN%\bin\aarch64-linux-android-strip
|
||||||
|
|
||||||
|
SET ANDROID_X86_CC=%ANDROID_X86_TOOLCHAIN%\bin\i686-linux-android-clang
|
||||||
|
SET ANDROID_X86_STRIP=%ANDROID_X86_TOOLCHAIN%\bin\i686-linux-android-strip
|
||||||
|
|
||||||
|
MKDIR %DEPS%>nul 2>nul
|
||||||
|
MKDIR %TARGET%\armeabi-v7a>nul 2>nul
|
||||||
|
MKDIR %TARGET%\x86>nul 2>nul
|
||||||
|
MKDIR %TARGET%\arm64-v8a>nul 2>nul
|
||||||
|
|
||||||
|
IF NOT EXIST %ANDROID_ARM_CC% (
|
||||||
|
ECHO "Make standalone toolchain for ARM arch"
|
||||||
|
%ANDROID_NDK_HOME%\build\tools\make_standalone_toolchain.py --arch arm ^
|
||||||
|
--api %MIN_API% --install-dir %ANDROID_ARM_TOOLCHAIN%
|
||||||
|
)
|
||||||
|
|
||||||
|
IF NOT EXIST %ANDROID_ARM64_CC% (
|
||||||
|
ECHO "Make standalone toolchain for ARM64 arch"
|
||||||
|
%ANDROID_NDK_HOME%\build\tools\make_standalone_toolchain.py --arch arm64 ^
|
||||||
|
--api %MIN_API% --install-dir %ANDROID_ARM64_TOOLCHAIN%
|
||||||
|
)
|
||||||
|
|
||||||
|
IF NOT EXIST %ANDROID_X86_CC% (
|
||||||
|
ECHO "Make standalone toolchain for X86 arch"
|
||||||
|
%ANDROID_NDK_HOME%\build\tools\make_standalone_toolchain.py --arch x86 ^
|
||||||
|
--api %MIN_API% --install-dir %ANDROID_X86_TOOLCHAIN%
|
||||||
|
)
|
||||||
|
|
||||||
|
IF NOT EXIST %DIR%\go\bin\go.exe (
|
||||||
|
ECHO "Build the custom go"
|
||||||
|
|
||||||
|
PUSHD %DIR%\go\src
|
||||||
|
CALL make.bat
|
||||||
|
POPD
|
||||||
|
)
|
||||||
|
|
||||||
|
SET GOROOT=%DIR%\go
|
||||||
|
SET GOPATH=%DIR%
|
||||||
|
SET PATH=%GOROOT%\bin;%GOPATH%\bin;%PATH%
|
||||||
|
|
||||||
|
SET BUILD=1
|
||||||
|
IF EXIST "%TARGET%\armeabi-v7a\liboverture.so" (
|
||||||
|
IF EXIST "%TARGET%\arm64-v8a\liboverture.so" (
|
||||||
|
IF EXIST "%TARGET%\x86\liboverture.so" (
|
||||||
|
SET BUILD=0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
IF %BUILD% == 1 (
|
||||||
|
ECHO "Get dependences for overture"
|
||||||
|
go.exe get -u github.com\tools\godep
|
||||||
|
|
||||||
|
PUSHD %GOPATH%\src\github.com\shadowsocks\overture\main
|
||||||
|
godep.exe restore
|
||||||
|
|
||||||
|
ECHO "Cross compile overture for arm"
|
||||||
|
IF NOT EXIST "%TARGET%\armeabi-v7a\liboverture.so" (
|
||||||
|
SETLOCAL
|
||||||
|
SET CGO_ENABLED=1
|
||||||
|
SET CC=%ANDROID_ARM_CC%
|
||||||
|
SET GOOS=android
|
||||||
|
SET GOARCH=arm
|
||||||
|
SET GOARM=7
|
||||||
|
go.exe build -ldflags="-s -w"
|
||||||
|
%ANDROID_ARM_STRIP% main
|
||||||
|
MOVE main %TARGET%\armeabi-v7a\liboverture.so>nul 2>nul
|
||||||
|
ENDLOCAL
|
||||||
|
)
|
||||||
|
|
||||||
|
ECHO "Cross compile overture for arm64"
|
||||||
|
IF NOT EXIST "%TARGET%\arm64-v8a\liboverture.so" (
|
||||||
|
SETLOCAL
|
||||||
|
SET CGO_ENABLED=1
|
||||||
|
SET CC=%ANDROID_ARM64_CC%
|
||||||
|
SET GOOS=android
|
||||||
|
SET GOARCH=arm64
|
||||||
|
go.exe build -ldflags="-s -w"
|
||||||
|
%ANDROID_ARM64_STRIP% main
|
||||||
|
MOVE main %TARGET%\arm64-v8a\liboverture.so>nul 2>nul
|
||||||
|
ENDLOCAL
|
||||||
|
)
|
||||||
|
|
||||||
|
ECHO "Cross compile overture for x86"
|
||||||
|
IF NOT EXIST "%TARGET%\x86\liboverture.so" (
|
||||||
|
SETLOCAL
|
||||||
|
SET CGO_ENABLED=1
|
||||||
|
SET CC=%ANDROID_X86_CC%
|
||||||
|
SET GOOS=android
|
||||||
|
SET GOARCH=386
|
||||||
|
go.exe build -ldflags="-s -w"
|
||||||
|
%ANDROID_X86_STRIP% main
|
||||||
|
MOVE main %TARGET%\x86\liboverture.so>nul 2>nul
|
||||||
|
ENDLOCAL
|
||||||
|
)
|
||||||
|
|
||||||
|
POPD
|
||||||
|
)
|
||||||
|
|
||||||
|
ECHO "Successfully build overture"
|
||||||
|
ENDLOCAL
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
#Fri Dec 01 17:03:17 PST 2017
|
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4.1-all.zip
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
##
|
##
|
||||||
@@ -6,42 +6,6 @@
|
|||||||
##
|
##
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
|
||||||
DEFAULT_JVM_OPTS=""
|
|
||||||
|
|
||||||
APP_NAME="Gradle"
|
|
||||||
APP_BASE_NAME=`basename "$0"`
|
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
|
||||||
MAX_FD="maximum"
|
|
||||||
|
|
||||||
warn ( ) {
|
|
||||||
echo "$*"
|
|
||||||
}
|
|
||||||
|
|
||||||
die ( ) {
|
|
||||||
echo
|
|
||||||
echo "$*"
|
|
||||||
echo
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# OS specific support (must be 'true' or 'false').
|
|
||||||
cygwin=false
|
|
||||||
msys=false
|
|
||||||
darwin=false
|
|
||||||
case "`uname`" in
|
|
||||||
CYGWIN* )
|
|
||||||
cygwin=true
|
|
||||||
;;
|
|
||||||
Darwin* )
|
|
||||||
darwin=true
|
|
||||||
;;
|
|
||||||
MINGW* )
|
|
||||||
msys=true
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Attempt to set APP_HOME
|
# Attempt to set APP_HOME
|
||||||
# Resolve links: $0 may be a link
|
# Resolve links: $0 may be a link
|
||||||
PRG="$0"
|
PRG="$0"
|
||||||
@@ -60,6 +24,46 @@ cd "`dirname \"$PRG\"`/" >/dev/null
|
|||||||
APP_HOME="`pwd -P`"
|
APP_HOME="`pwd -P`"
|
||||||
cd "$SAVED" >/dev/null
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS=""
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD="maximum"
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
NONSTOP* )
|
||||||
|
nonstop=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM.
|
# Determine the Java command to use to start the JVM.
|
||||||
@@ -85,7 +89,7 @@ location of your Java installation."
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||||
MAX_FD_LIMIT=`ulimit -H -n`
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
if [ $? -eq 0 ] ; then
|
if [ $? -eq 0 ] ; then
|
||||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
@@ -150,11 +154,19 @@ if $cygwin ; then
|
|||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
# Escape application args
|
||||||
function splitJvmOpts() {
|
save () {
|
||||||
JVM_OPTS=("$@")
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
}
|
}
|
||||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
APP_ARGS=$(save "$@")
|
||||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
|
||||||
|
|
||||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
|
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||||
|
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
||||||
|
|||||||
@@ -8,14 +8,14 @@
|
|||||||
@rem Set local scope for the variables with windows NT shell
|
@rem Set local scope for the variables with windows NT shell
|
||||||
if "%OS%"=="Windows_NT" setlocal
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
|
||||||
set DEFAULT_JVM_OPTS=
|
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%" == "" set DIRNAME=.
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS=
|
||||||
|
|
||||||
@rem Find java.exe
|
@rem Find java.exe
|
||||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
@@ -46,10 +46,9 @@ echo location of your Java installation.
|
|||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:init
|
:init
|
||||||
@rem Get command-line arguments, handling Windowz variants
|
@rem Get command-line arguments, handling Windows variants
|
||||||
|
|
||||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
|
||||||
|
|
||||||
:win9xME_args
|
:win9xME_args
|
||||||
@rem Slurp the command line arguments.
|
@rem Slurp the command line arguments.
|
||||||
@@ -60,11 +59,6 @@ set _SKIP=2
|
|||||||
if "x%~1" == "x" goto execute
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
set CMD_LINE_ARGS=%*
|
set CMD_LINE_ARGS=%*
|
||||||
goto execute
|
|
||||||
|
|
||||||
:4NT_args
|
|
||||||
@rem Get arguments from the 4NT Shell from JP Software
|
|
||||||
set CMD_LINE_ARGS=%$
|
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import com.android.build.OutputFile
|
||||||
import java.util.regex.Matcher
|
import java.util.regex.Matcher
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
@@ -20,11 +21,10 @@ android {
|
|||||||
applicationId "com.github.shadowsocks"
|
applicationId "com.github.shadowsocks"
|
||||||
minSdkVersion rootProject.minSdkVersion
|
minSdkVersion rootProject.minSdkVersion
|
||||||
targetSdkVersion rootProject.sdkVersion
|
targetSdkVersion rootProject.sdkVersion
|
||||||
versionCode 204
|
versionCode 211
|
||||||
versionName "4.4.4"
|
versionName "4.4.6"
|
||||||
testApplicationId "com.github.shadowsocks.test"
|
testApplicationId "com.github.shadowsocks.test"
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables.useSupportLibrary true
|
|
||||||
resConfigs "fa", "fr", "ja", "ko", "ru", "zh-rCN", "zh-rTW"
|
resConfigs "fa", "fr", "ja", "ko", "ru", "zh-rCN", "zh-rTW"
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
@@ -37,6 +37,15 @@ android {
|
|||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lintOptions.checkReleaseBuilds false
|
||||||
|
splits {
|
||||||
|
abi {
|
||||||
|
enable true
|
||||||
|
reset()
|
||||||
|
include 'armeabi-v7a', 'arm64-v8a', 'x86'
|
||||||
|
universalApk true
|
||||||
|
}
|
||||||
|
}
|
||||||
sourceSets.main.jniLibs.srcDirs +=
|
sourceSets.main.jniLibs.srcDirs +=
|
||||||
new File(project(':core').buildDir, "intermediates/bundles/${getCurrentFlavor()}/jni")
|
new File(project(':core').buildDir, "intermediates/bundles/${getCurrentFlavor()}/jni")
|
||||||
sourceSets.main.jniLibs.srcDirs += new File(project(':core').projectDir, "src/overture/bin")
|
sourceSets.main.jniLibs.srcDirs += new File(project(':core').projectDir, "src/overture/bin")
|
||||||
@@ -48,17 +57,13 @@ dependencies {
|
|||||||
implementation "com.android.support:design:$supportLibraryVersion"
|
implementation "com.android.support:design:$supportLibraryVersion"
|
||||||
implementation "com.android.support:gridlayout-v7:$supportLibraryVersion"
|
implementation "com.android.support:gridlayout-v7:$supportLibraryVersion"
|
||||||
implementation 'com.futuremind.recyclerfastscroll:fastscroll:0.2.5'
|
implementation 'com.futuremind.recyclerfastscroll:fastscroll:0.2.5'
|
||||||
implementation 'com.evernote:android-job:1.2.1'
|
implementation 'com.evernote:android-job:1.2.2'
|
||||||
implementation "com.google.android.gms:play-services-ads:$playServicesVersion"
|
implementation "com.google.android.gms:play-services-ads:$playServicesVersion"
|
||||||
implementation "com.google.android.gms:play-services-analytics:$playServicesVersion"
|
implementation "com.google.android.gms:play-services-analytics:$playServicesVersion"
|
||||||
implementation "com.google.android.gms:play-services-gcm:$playServicesVersion"
|
|
||||||
implementation "com.google.firebase:firebase-config:$playServicesVersion"
|
implementation "com.google.firebase:firebase-config:$playServicesVersion"
|
||||||
implementation 'com.j256.ormlite:ormlite-android:5.0'
|
implementation 'com.j256.ormlite:ormlite-android:5.0'
|
||||||
implementation 'com.mikepenz:crossfader:1.5.1'
|
implementation 'com.mikepenz:crossfader:1.5.1'
|
||||||
implementation 'com.mikepenz:fastadapter:3.0.4'
|
|
||||||
implementation 'com.mikepenz:iconics-core:3.0.0'
|
|
||||||
implementation 'com.mikepenz:materialdrawer:6.0.2'
|
implementation 'com.mikepenz:materialdrawer:6.0.2'
|
||||||
implementation 'com.mikepenz:materialize:1.1.2'
|
|
||||||
implementation 'com.squareup.okhttp3:okhttp:3.9.1'
|
implementation 'com.squareup.okhttp3:okhttp:3.9.1'
|
||||||
implementation "com.takisoft.fix:preference-v7-simplemenu:$takisoftFixVersion"
|
implementation "com.takisoft.fix:preference-v7-simplemenu:$takisoftFixVersion"
|
||||||
implementation 'com.twofortyfouram:android-plugin-api-for-locale:1.0.2'
|
implementation 'com.twofortyfouram:android-plugin-api-for-locale:1.0.2'
|
||||||
@@ -76,3 +81,11 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'com.google.gms.google-services'
|
apply plugin: 'com.google.gms.google-services'
|
||||||
|
|
||||||
|
ext.abiCodes = ['armeabi-v7a': 1, 'arm64-v8a': 2, x86: 3]
|
||||||
|
if (getCurrentFlavor() == 'release') android.applicationVariants.all { variant ->
|
||||||
|
variant.outputs.each { output ->
|
||||||
|
def offset = project.ext.abiCodes.get(output.getFilter(OutputFile.ABI))
|
||||||
|
if (offset != null) output.versionCodeOverride = variant.versionCode + offset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -171,9 +171,11 @@
|
|||||||
<service android:name="com.evernote.android.job.v14.PlatformAlarmService"
|
<service android:name="com.evernote.android.job.v14.PlatformAlarmService"
|
||||||
android:process=":bg"
|
android:process=":bg"
|
||||||
android:directBootAware="true"/>
|
android:directBootAware="true"/>
|
||||||
<service android:name="com.evernote.android.job.gcm.PlatformGcmService"
|
<service android:name="com.evernote.android.job.v14.PlatformAlarmServiceExact"
|
||||||
android:process=":bg"
|
android:process=":bg"
|
||||||
android:directBootAware="true"/>
|
android:directBootAware="true"/>
|
||||||
|
<service android:name="com.evernote.android.job.gcm.PlatformGcmService"
|
||||||
|
tools:node="remove"/>
|
||||||
<service android:name="com.evernote.android.job.JobRescheduleService"
|
<service android:name="com.evernote.android.job.JobRescheduleService"
|
||||||
android:process=":bg"
|
android:process=":bg"
|
||||||
android:directBootAware="true"/>
|
android:directBootAware="true"/>
|
||||||
|
|||||||
@@ -4,10 +4,13 @@
|
|||||||
|
|
||||||
[proxy_list]
|
[proxy_list]
|
||||||
# Telegram IPs$
|
# Telegram IPs$
|
||||||
91.108.4.0/22
|
91.108.56.0/23
|
||||||
91.108.56.0/22
|
91.108.56.0/22
|
||||||
|
91.108.4.0/22
|
||||||
|
149.154.172.0/22
|
||||||
|
149.154.168.0/22
|
||||||
|
149.154.164.0/22
|
||||||
109.239.140.0/24
|
109.239.140.0/24
|
||||||
149.154.160.0/20
|
|
||||||
(^|\.)4tern\.com$
|
(^|\.)4tern\.com$
|
||||||
(^|\.)adorama\.com$
|
(^|\.)adorama\.com$
|
||||||
(^|\.)akiba-web\.com$
|
(^|\.)akiba-web\.com$
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ import android.content.pm.PackageManager
|
|||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.LocaleList
|
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.support.annotation.RequiresApi
|
import android.support.annotation.RequiresApi
|
||||||
import android.support.v4.os.UserManagerCompat
|
import android.support.v4.os.UserManagerCompat
|
||||||
@@ -59,20 +58,11 @@ import com.j256.ormlite.logger.LocalLog
|
|||||||
import com.takisoft.fix.support.v7.preference.PreferenceFragmentCompat
|
import com.takisoft.fix.support.v7.preference.PreferenceFragmentCompat
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class App : Application() {
|
class App : Application() {
|
||||||
companion object {
|
companion object {
|
||||||
lateinit var app: App
|
lateinit var app: App
|
||||||
private const val TAG = "ShadowsocksApplication"
|
private const val TAG = "ShadowsocksApplication"
|
||||||
|
|
||||||
// The ones in Locale doesn't have script included
|
|
||||||
private val SIMPLIFIED_CHINESE by lazy {
|
|
||||||
if (Build.VERSION.SDK_INT >= 21) Locale.forLanguageTag("zh-Hans-CN") else Locale.SIMPLIFIED_CHINESE
|
|
||||||
}
|
|
||||||
private val TRADITIONAL_CHINESE by lazy {
|
|
||||||
if (Build.VERSION.SDK_INT >= 21) Locale.forLanguageTag("zh-Hant-TW") else Locale.TRADITIONAL_CHINESE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val handler by lazy { Handler(Looper.getMainLooper()) }
|
val handler by lazy { Handler(Looper.getMainLooper()) }
|
||||||
@@ -112,59 +102,11 @@ class App : Application() {
|
|||||||
t.printStackTrace()
|
t.printStackTrace()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkChineseLocale(config: Configuration) {
|
|
||||||
fun check(locale: Locale): Locale? {
|
|
||||||
if (locale.language != "zh") return null
|
|
||||||
when (locale.country) { "CN", "TW" -> return null }
|
|
||||||
if (Build.VERSION.SDK_INT >= 21) when (locale.script) {
|
|
||||||
"Hans" -> return SIMPLIFIED_CHINESE
|
|
||||||
"Hant" -> return TRADITIONAL_CHINESE
|
|
||||||
else -> Log.w(TAG, "Unknown zh locale script: ${locale.script}. Falling back to trying countries...")
|
|
||||||
}
|
|
||||||
when (locale.country) {
|
|
||||||
"SG" -> return SIMPLIFIED_CHINESE
|
|
||||||
"HK", "MO" -> return TRADITIONAL_CHINESE
|
|
||||||
}
|
|
||||||
Log.w(TAG, "Unknown zh locale: %s. Falling back to zh-Hans-CN..."
|
|
||||||
.format(Locale.ENGLISH, if (Build.VERSION.SDK_INT >= 21) locale.toLanguageTag() else locale))
|
|
||||||
return SIMPLIFIED_CHINESE
|
|
||||||
}
|
|
||||||
if (Build.VERSION.SDK_INT >= 24) @RequiresApi(24) {
|
|
||||||
val localeList = config.locales
|
|
||||||
var changed = false
|
|
||||||
val newList = Array<Locale>(localeList.size(), { i ->
|
|
||||||
val locale = localeList[i]
|
|
||||||
val newLocale = check(locale)
|
|
||||||
if (newLocale == null) locale else {
|
|
||||||
changed = true
|
|
||||||
newLocale
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (changed) {
|
|
||||||
val newConfig = Configuration(config)
|
|
||||||
newConfig.locales = LocaleList(*(newList.distinct().toTypedArray()))
|
|
||||||
val res = resources
|
|
||||||
res.updateConfiguration(newConfig, res.displayMetrics)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
val newLocale = check(config.locale)
|
|
||||||
if (newLocale != null) {
|
|
||||||
val newConfig = Configuration(config)
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
newConfig.locale = newLocale
|
|
||||||
val res = resources
|
|
||||||
res.updateConfiguration(newConfig, res.displayMetrics)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
app = this
|
app = this
|
||||||
if (!BuildConfig.DEBUG) System.setProperty(LocalLog.LOCAL_LOG_LEVEL_PROPERTY, "ERROR")
|
if (!BuildConfig.DEBUG) System.setProperty(LocalLog.LOCAL_LOG_LEVEL_PROPERTY, "ERROR")
|
||||||
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
|
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
|
||||||
checkChineseLocale(resources.configuration)
|
|
||||||
PreferenceFragmentCompat.registerPreferenceFragment(IconListPreference::class.java,
|
PreferenceFragmentCompat.registerPreferenceFragment(IconListPreference::class.java,
|
||||||
BottomSheetPreferenceDialogFragment::class.java)
|
BottomSheetPreferenceDialogFragment::class.java)
|
||||||
|
|
||||||
@@ -203,6 +145,15 @@ class App : Application() {
|
|||||||
DataStore.publicStore.putLong(Key.assetUpdateTime, info.lastUpdateTime)
|
DataStore.publicStore.putLong(Key.assetUpdateTime, info.lastUpdateTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateNotificationChannels()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||||
|
super.onConfigurationChanged(newConfig)
|
||||||
|
updateNotificationChannels()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateNotificationChannels() {
|
||||||
if (Build.VERSION.SDK_INT >= 26) @RequiresApi(26) {
|
if (Build.VERSION.SDK_INT >= 26) @RequiresApi(26) {
|
||||||
val nm = getSystemService(NotificationManager::class.java)
|
val nm = getSystemService(NotificationManager::class.java)
|
||||||
nm.createNotificationChannels(listOf(
|
nm.createNotificationChannels(listOf(
|
||||||
@@ -216,11 +167,6 @@ class App : Application() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
|
||||||
super.onConfigurationChanged(newConfig)
|
|
||||||
checkChineseLocale(newConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun listenForPackageChanges(callback: () -> Unit): BroadcastReceiver {
|
fun listenForPackageChanges(callback: () -> Unit): BroadcastReceiver {
|
||||||
val filter = IntentFilter(Intent.ACTION_PACKAGE_ADDED)
|
val filter = IntentFilter(Intent.ACTION_PACKAGE_ADDED)
|
||||||
filter.addAction(Intent.ACTION_PACKAGE_REMOVED)
|
filter.addAction(Intent.ACTION_PACKAGE_REMOVED)
|
||||||
|
|||||||
@@ -80,13 +80,11 @@ class ProfileConfigFragment : PreferenceFragmentCompatDividers(), Toolbar.OnMenu
|
|||||||
val serviceMode = DataStore.serviceMode
|
val serviceMode = DataStore.serviceMode
|
||||||
findPreference(Key.remoteDns).isEnabled = serviceMode != Key.modeProxy
|
findPreference(Key.remoteDns).isEnabled = serviceMode != Key.modeProxy
|
||||||
isProxyApps = findPreference(Key.proxyApps) as SwitchPreference
|
isProxyApps = findPreference(Key.proxyApps) as SwitchPreference
|
||||||
if (Build.VERSION.SDK_INT < 21) isProxyApps.parent!!.removePreference(isProxyApps) else {
|
isProxyApps.isEnabled = serviceMode == Key.modeVpn
|
||||||
isProxyApps.isEnabled = serviceMode == Key.modeVpn
|
isProxyApps.setOnPreferenceClickListener {
|
||||||
isProxyApps.setOnPreferenceClickListener {
|
startActivity(Intent(activity, AppManager::class.java))
|
||||||
startActivity(Intent(activity, AppManager::class.java))
|
isProxyApps.isChecked = true
|
||||||
isProxyApps.isChecked = true
|
false
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
findPreference(Key.udpdns).isEnabled = serviceMode != Key.modeProxy
|
findPreference(Key.udpdns).isEnabled = serviceMode != Key.modeProxy
|
||||||
plugin = findPreference(Key.plugin) as IconListPreference
|
plugin = findPreference(Key.plugin) as IconListPreference
|
||||||
|
|||||||
@@ -20,49 +20,19 @@
|
|||||||
|
|
||||||
package com.github.shadowsocks.bg
|
package com.github.shadowsocks.bg
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.net.ConnectivityManager
|
|
||||||
import android.net.LinkProperties
|
|
||||||
import android.os.Build
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.github.shadowsocks.App.Companion.app
|
import com.github.shadowsocks.App.Companion.app
|
||||||
import com.github.shadowsocks.BuildConfig
|
import com.github.shadowsocks.BuildConfig
|
||||||
import okhttp3.Dns as Okdns
|
|
||||||
import org.xbill.DNS.*
|
import org.xbill.DNS.*
|
||||||
import java.net.Inet6Address
|
import java.net.Inet6Address
|
||||||
import java.net.InetAddress
|
import java.net.InetAddress
|
||||||
import java.net.NetworkInterface
|
import java.net.NetworkInterface
|
||||||
import java.net.UnknownHostException
|
import java.net.UnknownHostException
|
||||||
import java.util.*
|
import okhttp3.Dns as Okdns
|
||||||
|
|
||||||
object Dns {
|
object Dns {
|
||||||
private const val TAG = "Dns"
|
private const val TAG = "Dns"
|
||||||
|
|
||||||
@Throws(Exception::class)
|
|
||||||
fun getDnsResolver(context: Context): String {
|
|
||||||
val dnsResolvers = getDnsResolvers(context)
|
|
||||||
if (dnsResolvers.isEmpty()) throw Exception("Couldn't find an active DNS resolver")
|
|
||||||
val dnsResolver = dnsResolvers.iterator().next().toString()
|
|
||||||
if (dnsResolver.startsWith("/")) return dnsResolver.substring(1)
|
|
||||||
return dnsResolver
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(Exception::class)
|
|
||||||
private fun getDnsResolvers(context: Context): Collection<InetAddress> {
|
|
||||||
val addresses = ArrayList<InetAddress>()
|
|
||||||
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
|
||||||
val classLinkProperties = Class.forName("android.net.LinkProperties")
|
|
||||||
val getActiveLinkPropertiesMethod = ConnectivityManager::class.java.getMethod("getActiveLinkProperties")
|
|
||||||
val linkProperties = getActiveLinkPropertiesMethod.invoke(connectivityManager)
|
|
||||||
if (linkProperties != null) {
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
val dnses = classLinkProperties.getMethod("getDnses").invoke(linkProperties) as Collection<*>
|
|
||||||
dnses.mapTo(addresses) { it as InetAddress }
|
|
||||||
} else addresses.addAll((linkProperties as LinkProperties).dnsServers)
|
|
||||||
}
|
|
||||||
return addresses
|
|
||||||
}
|
|
||||||
|
|
||||||
private val hasIPv6Support get() = try {
|
private val hasIPv6Support get() = try {
|
||||||
val result = NetworkInterface.getNetworkInterfaces().asSequence().flatMap { it.inetAddresses.asSequence() }
|
val result = NetworkInterface.getNetworkInterfaces().asSequence().flatMap { it.inetAddresses.asSequence() }
|
||||||
.count { it is Inet6Address && !it.isLoopbackAddress && !it.isLinkLocalAddress } > 0
|
.count { it is Inet6Address && !it.isLoopbackAddress && !it.isLinkLocalAddress } > 0
|
||||||
|
|||||||
@@ -47,14 +47,14 @@ object LocalDnsService {
|
|||||||
val data = data
|
val data = data
|
||||||
val profile = data.profile!!
|
val profile = data.profile!!
|
||||||
|
|
||||||
fun makeDns(name: String, address: String, edns: Boolean = true): JSONObject {
|
fun makeDns(name: String, address: String, timeout: Int, edns: Boolean = true): JSONObject {
|
||||||
val dns = JSONObject()
|
val dns = JSONObject()
|
||||||
.put("Name", name)
|
.put("Name", name)
|
||||||
.put("Address", (when (address.parseNumericAddress()) {
|
.put("Address", (when (address.parseNumericAddress()) {
|
||||||
is Inet6Address -> "[$address]"
|
is Inet6Address -> "[$address]"
|
||||||
else -> address
|
else -> address
|
||||||
}) + ":53")
|
}) + ":53")
|
||||||
.put("Timeout", 6)
|
.put("Timeout", timeout)
|
||||||
.put("EDNSClientSubnet", JSONObject().put("Policy", "disable"))
|
.put("EDNSClientSubnet", JSONObject().put("Policy", "disable"))
|
||||||
if (edns) dns
|
if (edns) dns
|
||||||
.put("Protocol", "tcp")
|
.put("Protocol", "tcp")
|
||||||
@@ -70,21 +70,15 @@ object LocalDnsService {
|
|||||||
.put("RedirectIPv6Record", true)
|
.put("RedirectIPv6Record", true)
|
||||||
.put("DomainBase64Decode", false)
|
.put("DomainBase64Decode", false)
|
||||||
.put("HostsFile", "hosts")
|
.put("HostsFile", "hosts")
|
||||||
.put("MinimumTTL", 3600)
|
.put("MinimumTTL", 120)
|
||||||
.put("CacheSize", 4096)
|
.put("CacheSize", 4096)
|
||||||
val remoteDns = JSONArray(profile.remoteDns.split(",")
|
val remoteDns = JSONArray(profile.remoteDns.split(",")
|
||||||
.mapIndexed { i, dns -> makeDns("UserDef-" + i, dns.trim()) })
|
.mapIndexed { i, dns -> makeDns("UserDef-" + i, dns.trim(), 9) })
|
||||||
val localDns = JSONArray(arrayOf(
|
val localDns = JSONArray(arrayOf(
|
||||||
makeDns("Primary-1", "119.29.29.29", false),
|
makeDns("Primary-1", "119.29.29.29", 3, false),
|
||||||
makeDns("Primary-2", "114.114.114.114", false)
|
makeDns("Primary-2", "114.114.114.114", 3, false)
|
||||||
))
|
))
|
||||||
|
|
||||||
this as Context
|
|
||||||
try {
|
|
||||||
val localLinkDns = Dns.getDnsResolver(this)
|
|
||||||
localDns.put(makeDns("Primary-3", localLinkDns, false))
|
|
||||||
} catch (_: Exception) { } // ignore
|
|
||||||
|
|
||||||
when (profile.route) {
|
when (profile.route) {
|
||||||
Acl.BYPASS_CHN, Acl.BYPASS_LAN_CHN, Acl.GFWLIST, Acl.CUSTOM_RULES -> config
|
Acl.BYPASS_CHN, Acl.BYPASS_LAN_CHN, Acl.GFWLIST, Acl.CUSTOM_RULES -> config
|
||||||
.put("PrimaryDNS", localDns)
|
.put("PrimaryDNS", localDns)
|
||||||
|
|||||||
@@ -40,8 +40,7 @@ import java.util.*
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Android < 8 VPN: always invisible because of VPN notification/icon
|
* Android < 8 VPN: always invisible because of VPN notification/icon
|
||||||
* Android 4.x other: always visible
|
* Android < 8 other: only invisible in (possibly unsecure) lockscreen
|
||||||
* Android 5-7 other: only invisible in (possibly unsecure) lockscreen
|
|
||||||
* Android 8+: always visible due to system limitations
|
* Android 8+: always visible due to system limitations
|
||||||
* (user can choose to hide the notification in secure lockscreen or anywhere)
|
* (user can choose to hide the notification in secure lockscreen or anywhere)
|
||||||
*/
|
*/
|
||||||
@@ -85,24 +84,22 @@ class ServiceNotification(private val service: BaseService.Interface, profileNam
|
|||||||
if (Build.VERSION.SDK_INT < 24) builder.addAction(R.drawable.ic_navigation_close,
|
if (Build.VERSION.SDK_INT < 24) builder.addAction(R.drawable.ic_navigation_close,
|
||||||
service.getString(R.string.stop), PendingIntent.getBroadcast(service, 0, Intent(Action.CLOSE), 0))
|
service.getString(R.string.stop), PendingIntent.getBroadcast(service, 0, Intent(Action.CLOSE), 0))
|
||||||
val power = service.getSystemService(Context.POWER_SERVICE) as PowerManager
|
val power = service.getSystemService(Context.POWER_SERVICE) as PowerManager
|
||||||
update(if (if (Build.VERSION.SDK_INT >= 20) power.isInteractive else @Suppress("DEPRECATION") power.isScreenOn)
|
update(if (power.isInteractive) Intent.ACTION_SCREEN_ON else Intent.ACTION_SCREEN_OFF, true)
|
||||||
Intent.ACTION_SCREEN_ON else Intent.ACTION_SCREEN_OFF, true)
|
|
||||||
val screenFilter = IntentFilter()
|
val screenFilter = IntentFilter()
|
||||||
screenFilter.addAction(Intent.ACTION_SCREEN_ON)
|
screenFilter.addAction(Intent.ACTION_SCREEN_ON)
|
||||||
screenFilter.addAction(Intent.ACTION_SCREEN_OFF)
|
screenFilter.addAction(Intent.ACTION_SCREEN_OFF)
|
||||||
if (visible && Build.VERSION.SDK_INT in 21 until 26) screenFilter.addAction(Intent.ACTION_USER_PRESENT)
|
if (visible && Build.VERSION.SDK_INT < 26) screenFilter.addAction(Intent.ACTION_USER_PRESENT)
|
||||||
service.registerReceiver(lockReceiver, screenFilter)
|
service.registerReceiver(lockReceiver, screenFilter)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun update(action: String, forceShow: Boolean = false) {
|
private fun update(action: String, forceShow: Boolean = false) {
|
||||||
if (forceShow || service.data.state == BaseService.CONNECTED) when (action) {
|
if (forceShow || service.data.state == BaseService.CONNECTED) when (action) {
|
||||||
Intent.ACTION_SCREEN_OFF -> {
|
Intent.ACTION_SCREEN_OFF -> {
|
||||||
setVisible(visible && Build.VERSION.SDK_INT < 21, forceShow)
|
setVisible(false, forceShow)
|
||||||
unregisterCallback() // unregister callback to save battery
|
unregisterCallback() // unregister callback to save battery
|
||||||
}
|
}
|
||||||
Intent.ACTION_SCREEN_ON -> {
|
Intent.ACTION_SCREEN_ON -> {
|
||||||
setVisible(visible && (Build.VERSION.SDK_INT < 21 || !keyGuard.inKeyguardRestrictedInputMode()),
|
setVisible(visible && !keyGuard.inKeyguardRestrictedInputMode(), forceShow)
|
||||||
forceShow)
|
|
||||||
service.data.binder.registerCallback(callback)
|
service.data.binder.registerCallback(callback)
|
||||||
service.data.binder.startListeningForBandwidth(callback)
|
service.data.binder.startListeningForBandwidth(callback)
|
||||||
callbackRegistered = true
|
callbackRegistered = true
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import android.app.Service
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.net.LocalSocket
|
import android.net.LocalSocket
|
||||||
import android.os.Build
|
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import android.os.ParcelFileDescriptor
|
import android.os.ParcelFileDescriptor
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
@@ -140,7 +139,7 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
|
|||||||
builder.addRoute("::", 0)
|
builder.addRoute("::", 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 21 && profile.proxyApps) {
|
if (profile.proxyApps) {
|
||||||
val me = packageName
|
val me = packageName
|
||||||
profile.individual.split('\n')
|
profile.individual.split('\n')
|
||||||
.filter { it != me }
|
.filter { it != me }
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import android.os.Bundle
|
|||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.support.design.widget.BottomSheetDialog
|
import android.support.design.widget.BottomSheetDialog
|
||||||
import android.support.v7.preference.PreferenceDialogFragmentCompat
|
import android.support.v7.preference.PreferenceDialogFragmentCompat
|
||||||
|
import android.support.v7.widget.DefaultItemAnimator
|
||||||
import android.support.v7.widget.LinearLayoutManager
|
import android.support.v7.widget.LinearLayoutManager
|
||||||
import android.support.v7.widget.RecyclerView
|
import android.support.v7.widget.RecyclerView
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
@@ -107,10 +108,12 @@ class BottomSheetPreferenceDialogFragment : PreferenceDialogFragmentCompat() {
|
|||||||
recycler.setPadding(0, padding, 0, padding)
|
recycler.setPadding(0, padding, 0, padding)
|
||||||
recycler.setHasFixedSize(true)
|
recycler.setHasFixedSize(true)
|
||||||
recycler.layoutManager = LinearLayoutManager(activity)
|
recycler.layoutManager = LinearLayoutManager(activity)
|
||||||
|
recycler.itemAnimator = DefaultItemAnimator()
|
||||||
recycler.adapter = IconListAdapter(dialog)
|
recycler.adapter = IconListAdapter(dialog)
|
||||||
recycler.layoutParams = ViewGroup.LayoutParams(
|
recycler.layoutParams = ViewGroup.LayoutParams(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
dialog.setContentView(recycler)
|
dialog.setContentView(recycler)
|
||||||
|
dialog.findViewById<View>(R.id.touch_outside)!!.isFocusable = false
|
||||||
return dialog
|
return dialog
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ package com.github.shadowsocks.tasker
|
|||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.v7.app.AppCompatActivity
|
import android.support.v7.app.AppCompatActivity
|
||||||
import android.support.v7.widget.DefaultItemAnimator
|
import android.support.v7.widget.DefaultItemAnimator
|
||||||
@@ -71,13 +70,12 @@ class ConfigActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
inner class ProfilesAdapter : RecyclerView.Adapter<ProfileViewHolder>() {
|
inner class ProfilesAdapter : RecyclerView.Adapter<ProfileViewHolder>() {
|
||||||
internal val profiles = ProfileManager.getAllProfiles()?.toMutableList() ?: mutableListOf()
|
internal val profiles = ProfileManager.getAllProfiles()?.toMutableList() ?: mutableListOf()
|
||||||
private val name = "select_dialog_singlechoice_" + (if (Build.VERSION.SDK_INT >= 21) "material" else "holo")
|
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: ProfileViewHolder, position: Int) =
|
override fun onBindViewHolder(holder: ProfileViewHolder, position: Int) =
|
||||||
if (position == 0) holder.bindDefault() else holder.bind(profiles[position - 1])
|
if (position == 0) holder.bindDefault() else holder.bind(profiles[position - 1])
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProfileViewHolder = ProfileViewHolder(
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProfileViewHolder = ProfileViewHolder(
|
||||||
LayoutInflater.from(parent.context).inflate(Resources.getSystem()
|
LayoutInflater.from(parent.context).inflate(Resources.getSystem()
|
||||||
.getIdentifier(name, "layout", "android"), parent, false))
|
.getIdentifier("select_dialog_singlechoice_material", "layout", "android"), parent, false))
|
||||||
override fun getItemCount(): Int = 1 + profiles.size
|
override fun getItemCount(): Int = 1 + profiles.size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import android.support.annotation.AttrRes
|
|||||||
import android.support.v4.app.Fragment
|
import android.support.v4.app.Fragment
|
||||||
import android.support.v4.app.FragmentManager
|
import android.support.v4.app.FragmentManager
|
||||||
import android.support.v7.util.SortedList
|
import android.support.v7.util.SortedList
|
||||||
import android.view.accessibility.AccessibilityManager
|
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import com.github.shadowsocks.App.Companion.app
|
import com.github.shadowsocks.App.Companion.app
|
||||||
import com.github.shadowsocks.JniHelper
|
import com.github.shadowsocks.JniHelper
|
||||||
@@ -22,11 +21,6 @@ private val fieldChildFragmentManager by lazy {
|
|||||||
field
|
field
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isAccessibilityEnabled(context: Context): Boolean {
|
|
||||||
val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
|
|
||||||
return am.isEnabled()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun String.isNumericAddress() = JniHelper.parseNumericAddress(this) != null
|
fun String.isNumericAddress() = JniHelper.parseNumericAddress(this) != null
|
||||||
fun String.parseNumericAddress(): InetAddress? {
|
fun String.parseNumericAddress(): InetAddress? {
|
||||||
val addr = JniHelper.parseNumericAddress(this)
|
val addr = JniHelper.parseNumericAddress(this)
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* *
|
|
||||||
* Copyright (C) 2017 by Max Lv <max.c.lv@gmail.com> *
|
|
||||||
* Copyright (C) 2017 by Mygod Studio <contact-shadowsocks-android@mygod.be> *
|
|
||||||
* *
|
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
|
||||||
* it under the terms of the GNU General Public License as published by *
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
* This program is distributed in the hope that it will be useful, *
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
||||||
* GNU General Public License for more details. *
|
|
||||||
* *
|
|
||||||
* You should have received a copy of the GNU General Public License *
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
|
||||||
* *
|
|
||||||
*******************************************************************************/
|
|
||||||
|
|
||||||
package com.github.shadowsocks.widget
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.support.design.widget.CoordinatorLayout
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.view.View
|
|
||||||
import com.github.shadowsocks.R
|
|
||||||
|
|
||||||
class BottomMarginBehavior : CoordinatorLayout.Behavior<View> {
|
|
||||||
constructor() : super()
|
|
||||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
|
|
||||||
|
|
||||||
override fun layoutDependsOn(parent: CoordinatorLayout, child: View, dependency: View): Boolean =
|
|
||||||
dependency.id == R.id.stat // sorry I'm too lazy to write an attribute
|
|
||||||
|
|
||||||
override fun onDependentViewChanged(parent: CoordinatorLayout, child: View, dependency: View): Boolean {
|
|
||||||
(child.layoutParams as CoordinatorLayout.LayoutParams).bottomMargin = (parent.height - dependency.y).toInt()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -20,34 +20,27 @@
|
|||||||
|
|
||||||
package com.github.shadowsocks.widget
|
package com.github.shadowsocks.widget
|
||||||
|
|
||||||
import android.animation.Animator
|
|
||||||
import android.animation.AnimatorListenerAdapter
|
|
||||||
import android.animation.ValueAnimator
|
import android.animation.ValueAnimator
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Build
|
|
||||||
import android.support.design.widget.CoordinatorLayout
|
import android.support.design.widget.CoordinatorLayout
|
||||||
import android.support.design.widget.SnackbarAnimation
|
|
||||||
import android.support.design.widget.Snackbar
|
import android.support.design.widget.Snackbar
|
||||||
import android.support.v4.view.ViewCompat
|
import android.support.design.widget.SnackbarAnimation
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.view.accessibility.AccessibilityManager
|
||||||
import com.github.shadowsocks.utils.isAccessibilityEnabled
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Full credits go to: https://stackoverflow.com/a/35904421/2245107
|
* Full credits go to: https://stackoverflow.com/a/35904421/2245107
|
||||||
*/
|
*/
|
||||||
class MoveUpwardBehavior : CoordinatorLayout.Behavior<View> {
|
class ShrinkUpwardBehavior(context: Context, attrs: AttributeSet) : CoordinatorLayout.Behavior<View>(context, attrs) {
|
||||||
constructor() : super()
|
private val accessibility = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
|
||||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
|
|
||||||
|
|
||||||
override fun layoutDependsOn(parent: CoordinatorLayout, child: View, dependency: View): Boolean =
|
override fun layoutDependsOn(parent: CoordinatorLayout, child: View, dependency: View): Boolean =
|
||||||
dependency is Snackbar.SnackbarLayout
|
dependency is Snackbar.SnackbarLayout
|
||||||
|
|
||||||
override fun onDependentViewChanged(parent: CoordinatorLayout, child: View, dependency: View): Boolean {
|
override fun onDependentViewChanged(parent: CoordinatorLayout, child: View, dependency: View): Boolean {
|
||||||
val params = child.layoutParams
|
child.layoutParams.height = dependency.y.toInt()
|
||||||
params.height = parent.height - dependency.height
|
child.requestLayout()
|
||||||
child.layoutParams = params
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,25 +48,18 @@ class MoveUpwardBehavior : CoordinatorLayout.Behavior<View> {
|
|||||||
* Based on BaseTransientBottomBar.animateViewOut (support lib 27.0.2).
|
* Based on BaseTransientBottomBar.animateViewOut (support lib 27.0.2).
|
||||||
*/
|
*/
|
||||||
override fun onDependentViewRemoved(parent: CoordinatorLayout, child: View, dependency: View) {
|
override fun onDependentViewRemoved(parent: CoordinatorLayout, child: View, dependency: View) {
|
||||||
if (!isAccessibilityEnabled(parent.getContext())) {
|
if (accessibility.isEnabled) child.layoutParams.height = parent.height else {
|
||||||
val animator = ValueAnimator()
|
val animator = ValueAnimator()
|
||||||
val start = child.height
|
val start = child.height
|
||||||
animator.setIntValues(start, parent.height)
|
animator.setIntValues(start, parent.height)
|
||||||
animator.interpolator = SnackbarAnimation.FAST_OUT_SLOW_IN_INTERPOLATOR
|
animator.interpolator = SnackbarAnimation.FAST_OUT_SLOW_IN_INTERPOLATOR
|
||||||
animator.duration = SnackbarAnimation.ANIMATION_DURATION
|
animator.duration = SnackbarAnimation.ANIMATION_DURATION
|
||||||
animator.addUpdateListener(object : ValueAnimator.AnimatorUpdateListener {
|
@Suppress("NAME_SHADOWING")
|
||||||
override fun onAnimationUpdate(animator: ValueAnimator) {
|
animator.addUpdateListener { animator ->
|
||||||
val currentValue = animator.animatedValue as Int
|
child.layoutParams.height = animator.animatedValue as Int
|
||||||
val params = child.layoutParams
|
child.requestLayout()
|
||||||
params.height = currentValue
|
}
|
||||||
child.layoutParams = params
|
|
||||||
}
|
|
||||||
})
|
|
||||||
animator.start()
|
animator.start()
|
||||||
} else {
|
|
||||||
val params = child.layoutParams
|
|
||||||
params.height = parent.height
|
|
||||||
child.layoutParams = params
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 198 B |
|
Before Width: | Height: | Size: 400 B |
|
Before Width: | Height: | Size: 156 B |
|
Before Width: | Height: | Size: 298 B |
@@ -1,25 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item>
|
|
||||||
<shape android:shape="rectangle">
|
|
||||||
<solid android:color="@color/material_primary_300" />
|
|
||||||
</shape>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<selector android:enterFadeDuration="@android:integer/config_mediumAnimTime"
|
|
||||||
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
|
|
||||||
<item android:state_selected="true">
|
|
||||||
<shape android:shape="rectangle">
|
|
||||||
<solid android:color="@color/material_green_700" />
|
|
||||||
</shape>
|
|
||||||
</item>
|
|
||||||
</selector>
|
|
||||||
</item>
|
|
||||||
<!-- android:start not available until API 23 -->
|
|
||||||
<item android:left="8dp">
|
|
||||||
<shape android:shape="rectangle">
|
|
||||||
<solid android:color="@android:color/white" />
|
|
||||||
</shape>
|
|
||||||
</item>
|
|
||||||
<item android:drawable="?android:attr/selectableItemBackground"/>
|
|
||||||
</layer-list>
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="?android:colorControlHighlight">
|
|
||||||
<item>
|
|
||||||
<selector android:enterFadeDuration="@android:integer/config_mediumAnimTime"
|
|
||||||
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
|
|
||||||
<item android:state_selected="true">
|
|
||||||
<color android:color="@color/material_primary_100"/>
|
|
||||||
</item>
|
|
||||||
</selector>
|
|
||||||
</item>
|
|
||||||
</ripple>
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="?android:colorControlHighlight">
|
|
||||||
<item>
|
|
||||||
<color android:color="@color/material_primary_300"/>
|
|
||||||
</item>
|
|
||||||
</ripple>
|
|
||||||
|
Before Width: | Height: | Size: 228 B |
|
Before Width: | Height: | Size: 510 B |
|
Before Width: | Height: | Size: 284 B |
|
Before Width: | Height: | Size: 748 B |
|
Before Width: | Height: | Size: 364 B |
@@ -15,18 +15,11 @@
|
|||||||
</item>
|
</item>
|
||||||
</selector>
|
</selector>
|
||||||
</item>
|
</item>
|
||||||
<item android:left="@dimen/profile_padding">
|
<!-- android:start not available until API 23 -->
|
||||||
|
<item android:left="8dp">
|
||||||
<shape android:shape="rectangle">
|
<shape android:shape="rectangle">
|
||||||
<solid android:color="@android:color/white" />
|
<solid android:color="@android:color/white" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item android:drawable="?android:attr/selectableItemBackground"/>
|
||||||
<selector>
|
|
||||||
<item android:state_pressed="true">
|
|
||||||
<shape android:shape="rectangle">
|
|
||||||
<solid android:color="#12000000" />
|
|
||||||
</shape>
|
|
||||||
</item>
|
|
||||||
</selector>
|
|
||||||
</item>
|
|
||||||
</layer-list>
|
</layer-list>
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
android:enterFadeDuration="@android:integer/config_mediumAnimTime"
|
<item>
|
||||||
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
|
<selector android:enterFadeDuration="@android:integer/config_mediumAnimTime"
|
||||||
<item android:state_selected="true">
|
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
|
||||||
<color android:color="@color/material_primary_100"/>
|
<item android:state_selected="true">
|
||||||
|
<color android:color="@color/material_primary_100"/>
|
||||||
|
</item>
|
||||||
|
</selector>
|
||||||
</item>
|
</item>
|
||||||
</selector>
|
<item android:drawable="?android:attr/selectableItemBackground"/>
|
||||||
|
</layer-list>
|
||||||
|
|||||||
@@ -1,17 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<item>
|
<item>
|
||||||
<shape android:shape="rectangle">
|
<color android:color="@color/material_primary_300"/>
|
||||||
<solid android:color="@color/material_primary_300" />
|
|
||||||
</shape>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<selector>
|
|
||||||
<item android:state_pressed="true">
|
|
||||||
<shape android:shape="rectangle">
|
|
||||||
<solid android:color="#12000000" />
|
|
||||||
</shape>
|
|
||||||
</item>
|
|
||||||
</selector>
|
|
||||||
</item>
|
</item>
|
||||||
|
<item android:drawable="?android:attr/selectableItemBackground"/>
|
||||||
</layer-list>
|
</layer-list>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
app:layout_behavior="com.github.shadowsocks.widget.MoveUpwardBehavior">
|
app:layout_behavior="com.github.shadowsocks.widget.ShrinkUpwardBehavior">
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/fragment_holder"
|
android:id="@+id/fragment_holder"
|
||||||
@@ -148,7 +148,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:layout_marginTop="@dimen/fab_margin_top"
|
android:layout_marginTop="-28dp"
|
||||||
android:elevation="6dp"
|
android:elevation="6dp"
|
||||||
app:layout_anchor="@id/stat"
|
app:layout_anchor="@id/stat"
|
||||||
app:layout_anchorGravity="top|end">
|
app:layout_anchorGravity="top|end">
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<!-- misc -->
|
<!-- misc -->
|
||||||
<string name="profile">"پروفایل"</string>
|
<string name="profile">"پروفایل"</string>
|
||||||
<string name="connection_test_testing">"در حال آزمایش..."</string>
|
<string name="connection_test_testing">"در حال آزمایش…"</string>
|
||||||
|
|
||||||
<!-- proxy category -->
|
<!-- proxy category -->
|
||||||
<string name="profile_name">"نام پروفایل"</string>
|
<string name="profile_name">"نام پروفایل"</string>
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
<string name="invalid_server">"آدرس سرور نامعتبر است"</string>
|
<string name="invalid_server">"آدرس سرور نامعتبر است"</string>
|
||||||
<string name="service_failed">"اتصال به سرور ناموفق بود!"</string>
|
<string name="service_failed">"اتصال به سرور ناموفق بود!"</string>
|
||||||
<string name="stop">"غیرفعالکردن"</string>
|
<string name="stop">"غیرفعالکردن"</string>
|
||||||
<string name="stopping">"در حال قطعکردن اتصال..."</string>
|
<string name="stopping">"در حال قطعکردن اتصال…"</string>
|
||||||
<string name="profile_invalid_input">"هیچ پروفایل معتبری یافت نشد!"</string>
|
<string name="profile_invalid_input">"هیچ پروفایل معتبری یافت نشد!"</string>
|
||||||
|
|
||||||
<!-- alert category -->
|
<!-- alert category -->
|
||||||
@@ -33,7 +33,6 @@
|
|||||||
<string name="profiles">"پروفایلها"</string>
|
<string name="profiles">"پروفایلها"</string>
|
||||||
<string name="settings">"تنظیمات"</string>
|
<string name="settings">"تنظیمات"</string>
|
||||||
<string name="faq">"سوالات مداول"</string>
|
<string name="faq">"سوالات مداول"</string>
|
||||||
<string name="recovery">"ریست"</string>
|
|
||||||
<string name="about">"درباره ما"</string>
|
<string name="about">"درباره ما"</string>
|
||||||
<string name="edit">"ویرایش"</string>
|
<string name="edit">"ویرایش"</string>
|
||||||
<string name="share">"به اشتراک گذاری"</string>
|
<string name="share">"به اشتراک گذاری"</string>
|
||||||
@@ -52,9 +51,8 @@
|
|||||||
<!-- status -->
|
<!-- status -->
|
||||||
<string name="sent">"فرستادهشده:"</string>
|
<string name="sent">"فرستادهشده:"</string>
|
||||||
<string name="received">"دریافتشده:"</string>
|
<string name="received">"دریافتشده:"</string>
|
||||||
<string name="connecting">"در حال اتصال..."</string>
|
<string name="connecting">"در حال اتصال…"</string>
|
||||||
<string name="vpn_connected">"وصل شد. برای بررسی اتصال ضربه (Tap) بزنید."</string>
|
<string name="vpn_connected">"وصل شد. برای بررسی اتصال ضربه (Tap) بزنید."</string>
|
||||||
<string name="nat_connected">"اتصال برقرار است."</string>
|
|
||||||
<string name="not_connected">"اتصال برقرار نیست!"</string>
|
<string name="not_connected">"اتصال برقرار نیست!"</string>
|
||||||
<string name="route_entry_all">"همه"</string>
|
<string name="route_entry_all">"همه"</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,3 +1,35 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
|
<!-- misc -->
|
||||||
|
<string name="profile">"Profil"</string>
|
||||||
|
<string name="connection_test_error">"Impossible de détecter la connexion Internet :%s"</string>
|
||||||
|
<string name="connection_test_fail">"Internet Indisponible"</string>
|
||||||
|
<string name="connection_test_error_status_code">"Code de l'Erreur : #%d"</string>
|
||||||
|
<string name="proxy">"Serveur"</string>
|
||||||
|
<string name="sitekey">"Mot de passe"</string>
|
||||||
|
<string name="service_failed">"Échec de la connexion au serveur distant"</string>
|
||||||
|
|
||||||
|
<!-- alert category -->
|
||||||
|
<string name="close">"Fermer"</string>
|
||||||
|
<string name="profile_empty">"Veuillez sélectionner un profil"</string>
|
||||||
|
|
||||||
|
<!-- menu category -->
|
||||||
|
<string name="profiles">"Profils"</string>
|
||||||
|
<string name="settings">"Paramètres"</string>
|
||||||
|
<string name="about">"À propos"</string>
|
||||||
|
<string name="share">"Partager"</string>
|
||||||
|
<string name="add_profile">"Ajouter un Profil"</string>
|
||||||
|
<string name="action_apply_all">"Appliquer les Paramètres à tous les Profils"</string>
|
||||||
|
<string name="action_export">"Exporter vers le presse-papiers"</string>
|
||||||
|
<string name="action_import">"Importer depuis le presse-papiers"</string>
|
||||||
|
<string name="delete">"Supprimer"</string>
|
||||||
|
<string name="delete_confirm_prompt">"Êtes-vous sûr de vouloir supprimer ce profil?"</string>
|
||||||
|
<string name="share_qr_nfc">"QR Code/NFC"</string>
|
||||||
|
<string name="add_profile_methods_scan_qr_code">"Scanner le QR Code"</string>
|
||||||
|
<plurals name="removed">
|
||||||
|
<item quantity="one">"Supprimé"</item>
|
||||||
|
<item quantity="other">"%d éléments supprimés"</item>
|
||||||
|
</plurals>
|
||||||
|
<string name="undo">"Annuler"</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">"Shadowsocks"</string>
|
|
||||||
<string name="quick_toggle">"ON/OFF"</string>
|
<string name="quick_toggle">"ON/OFF"</string>
|
||||||
|
|
||||||
<!-- misc -->
|
<!-- misc -->
|
||||||
@@ -9,7 +8,6 @@
|
|||||||
<string name="remote_dns">"リモートDNS"</string>
|
<string name="remote_dns">"リモートDNS"</string>
|
||||||
<string name="stat_summary">"送信済み: \t%3$s\t↑\t%1$s/s
|
<string name="stat_summary">"送信済み: \t%3$s\t↑\t%1$s/s
|
||||||
受信済み: \t%4$s\t↓\t%2$s/s"</string>
|
受信済み: \t%4$s\t↓\t%2$s/s"</string>
|
||||||
|
|
||||||
<string name="connection_test_pending">"接続状況確認"</string>
|
<string name="connection_test_pending">"接続状況確認"</string>
|
||||||
<string name="connection_test_testing">"テスト中…"</string>
|
<string name="connection_test_testing">"テスト中…"</string>
|
||||||
<string name="connection_test_available">"成功: %dmsの遅延"</string>
|
<string name="connection_test_available">"成功: %dmsの遅延"</string>
|
||||||
@@ -35,10 +33,8 @@
|
|||||||
<string name="ipv6_summary">"リモートサーバーに IPv6 パケットを転送"</string>
|
<string name="ipv6_summary">"リモートサーバーに IPv6 パケットを転送"</string>
|
||||||
<string name="route_list">"プロキシ方式"</string>
|
<string name="route_list">"プロキシ方式"</string>
|
||||||
<string name="route_entry_gfwlist">"中国本土からアクセス不可なアドレス以外を迂回する"</string>
|
<string name="route_entry_gfwlist">"中国本土からアクセス不可なアドレス以外を迂回する"</string>
|
||||||
|
<string name="proxied_apps">"アプリ別のVPNモードを使用"</string>
|
||||||
<string name="proxied_apps">"アプリ別のプロキシを使用"</string>
|
<string name="proxied_apps_summary">"アプリ別のVPNモードを設定"</string>
|
||||||
|
|
||||||
<string name="proxied_apps_summary">"アプリ別でプロキシを指定、Android 4.x では必ずNATモードを使用して下さい"</string>
|
|
||||||
<string name="on">"ON"</string>
|
<string name="on">"ON"</string>
|
||||||
<string name="bypass_apps">"バイパスモード(迂回モード)"</string>
|
<string name="bypass_apps">"バイパスモード(迂回モード)"</string>
|
||||||
<string name="bypass_apps_summary">"このモードを選択した場合、指定したアプリのパケットはプロキシを経由しない"</string>
|
<string name="bypass_apps_summary">"このモードを選択した場合、指定したアプリのパケットはプロキシを経由しない"</string>
|
||||||
@@ -74,9 +70,7 @@
|
|||||||
<string name="profiles">"プロファイル"</string>
|
<string name="profiles">"プロファイル"</string>
|
||||||
<string name="settings">"オプション設定"</string>
|
<string name="settings">"オプション設定"</string>
|
||||||
<string name="faq">"よくある質問"</string>
|
<string name="faq">"よくある質問"</string>
|
||||||
<string name="faq_url">"https://github.com/shadowsocks/shadowsocks-android/blob/master/.github/faq.md"</string>
|
|
||||||
<string name="about">"本アプリについて"</string>
|
<string name="about">"本アプリについて"</string>
|
||||||
<string name="about_title">"Shadowsocks %s"</string>
|
|
||||||
<string name="edit">"編集"</string>
|
<string name="edit">"編集"</string>
|
||||||
<string name="share">"共有"</string>
|
<string name="share">"共有"</string>
|
||||||
<string name="add_profile">"プロファイルを追加"</string>
|
<string name="add_profile">"プロファイルを追加"</string>
|
||||||
@@ -127,10 +121,7 @@
|
|||||||
<string name="route_entry_bypass_chn">"中国本土のアドレスを迂回する"</string>
|
<string name="route_entry_bypass_chn">"中国本土のアドレスを迂回する"</string>
|
||||||
<string name="route_entry_bypass_lan_chn">"LAN 及び中国本土のアドレスを迂回する"</string>
|
<string name="route_entry_bypass_lan_chn">"LAN 及び中国本土のアドレスを迂回する"</string>
|
||||||
<string name="route_entry_chinalist">"中国本土のアドレス以外を迂回する"</string>
|
<string name="route_entry_chinalist">"中国本土のアドレス以外を迂回する"</string>
|
||||||
|
<string name="acl_rule_templates_generic">"サブネットまたはホスト名のPCREパターン"</string>
|
||||||
<string name="proxied_apps_summary_v21">"選択したアプリにプロキシを設定する"</string>
|
|
||||||
|
|
||||||
<string name="acl_rule_templates_generic">"URL/サブネット/ホスト名 PCRE パターン"</string>
|
|
||||||
<string name="acl_rule_templates_domain">"ドメイン及び全てのサブドメイン"</string>
|
<string name="acl_rule_templates_domain">"ドメイン及び全てのサブドメイン"</string>
|
||||||
|
|
||||||
<!-- plugin -->
|
<!-- plugin -->
|
||||||
@@ -148,7 +139,6 @@
|
|||||||
<string name="advanced">"アドバンス"</string>
|
<string name="advanced">"アドバンス"</string>
|
||||||
<string name="service_mode">"サービスモード"</string>
|
<string name="service_mode">"サービスモード"</string>
|
||||||
<string name="service_mode_proxy">"プロキシのみ"</string>
|
<string name="service_mode_proxy">"プロキシのみ"</string>
|
||||||
<string name="service_mode_vpn">"VPN"</string>
|
|
||||||
<string name="service_mode_transproxy">"トランスプロキシ"</string>
|
<string name="service_mode_transproxy">"トランスプロキシ"</string>
|
||||||
<string name="port_proxy">"SOCKS5プロキシポート"</string>
|
<string name="port_proxy">"SOCKS5プロキシポート"</string>
|
||||||
<string name="port_local_dns">"ローカルDNSポート"</string>
|
<string name="port_local_dns">"ローカルDNSポート"</string>
|
||||||
@@ -157,4 +147,7 @@
|
|||||||
<string name="service_transproxy">"トランスプロキシサービス"</string>
|
<string name="service_transproxy">"トランスプロキシサービス"</string>
|
||||||
<string name="vpn_permission_denied">"VPNサービス作成のアクセス許可が拒否されました"</string>
|
<string name="vpn_permission_denied">"VPNサービス作成のアクセス許可が拒否されました"</string>
|
||||||
<string name="auto_connect_summary_v24">"起動時にShadowsockを有効。 VPN常時接続の使用をお勧めします"</string>
|
<string name="auto_connect_summary_v24">"起動時にShadowsockを有効。 VPN常時接続の使用をお勧めします"</string>
|
||||||
</resources>
|
<string name="direct_boot_aware">"ダイレクトブート"</string>
|
||||||
|
<string name="direct_boot_aware_summary">"デバイスがロック解除される前にShadowsocksの自動起動を許可(選択されたプロファイル情報はより少ない保護を受けることになります)"</string>
|
||||||
|
<string name="acl_rule_online_config">"オンライン設定のURL"</string>
|
||||||
|
</resources>
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">"Shadowsocks"</string>
|
|
||||||
<string name="quick_toggle">"켜기/끄기"</string>
|
<string name="quick_toggle">"켜기/끄기"</string>
|
||||||
|
|
||||||
<!-- misc -->
|
<!-- misc -->
|
||||||
@@ -9,7 +8,9 @@
|
|||||||
<string name="remote_dns">"원격 DNS"</string>
|
<string name="remote_dns">"원격 DNS"</string>
|
||||||
<string name="stat_summary">"송신: \t%3$s\t↑\t%1$s/s
|
<string name="stat_summary">"송신: \t%3$s\t↑\t%1$s/s
|
||||||
수신: \t%4$s\t↓\t%2$s/s"</string>
|
수신: \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_testing">"검사 중…"</string>
|
||||||
<string name="connection_test_available">"성공: 지연시간 %dms"</string>
|
<string name="connection_test_available">"성공: 지연시간 %dms"</string>
|
||||||
@@ -34,11 +35,10 @@
|
|||||||
<string name="ipv6">"IPv6 라우팅"</string>
|
<string name="ipv6">"IPv6 라우팅"</string>
|
||||||
<string name="ipv6_summary">"IPv6 트래픽도 원격으로 리다이렉트 합니다"</string>
|
<string name="ipv6_summary">"IPv6 트래픽도 원격으로 리다이렉트 합니다"</string>
|
||||||
<string name="route_list">"라우팅 대상"</string>
|
<string name="route_list">"라우팅 대상"</string>
|
||||||
<string name="route_entry_gfwlist">"GFW List"</string>
|
|
||||||
|
|
||||||
|
<!-- Fuzzy -->
|
||||||
<string name="proxied_apps">"원하는 앱만 프락시 적용하기"</string>
|
<string name="proxied_apps">"원하는 앱만 프락시 적용하기"</string>
|
||||||
|
<string name="proxied_apps_summary">"선택한 앱에만 프락시를 적용합니다"</string>
|
||||||
<string name="proxied_apps_summary">"선택한 앱에만 프락시를 적용합니다. Android 4.x 이하에서는 NAT 모드를 써야 합니다."</string>
|
|
||||||
<string name="on">"활성화"</string>
|
<string name="on">"활성화"</string>
|
||||||
<string name="bypass_apps">"선택된 앱들만 프록시 적용 제외하기"</string>
|
<string name="bypass_apps">"선택된 앱들만 프록시 적용 제외하기"</string>
|
||||||
<string name="bypass_apps_summary">"이 옵션을 활성화하면 선택된 앱들은 프락시를 사용하지 않습니다"</string>
|
<string name="bypass_apps_summary">"이 옵션을 활성화하면 선택된 앱들은 프락시를 사용하지 않습니다"</string>
|
||||||
@@ -55,7 +55,6 @@
|
|||||||
<string name="service_failed">"원격 서버에 접속하는 데 실패했습니다"</string>
|
<string name="service_failed">"원격 서버에 접속하는 데 실패했습니다"</string>
|
||||||
<string name="stop">"중지"</string>
|
<string name="stop">"중지"</string>
|
||||||
<string name="stopping">"종료 중…"</string>
|
<string name="stopping">"종료 중…"</string>
|
||||||
<string name="vpn_error">"%s"</string>
|
|
||||||
<string name="reboot_required">"VPN 서비스를 시작하는 데 실패했습니다. 장치를 재시작해 보세요."</string>
|
<string name="reboot_required">"VPN 서비스를 시작하는 데 실패했습니다. 장치를 재시작해 보세요."</string>
|
||||||
<string name="profile_invalid_input">"올바른 프로필 데이터를 찾을 수 없습니다"</string>
|
<string name="profile_invalid_input">"올바른 프로필 데이터를 찾을 수 없습니다"</string>
|
||||||
|
|
||||||
@@ -74,13 +73,10 @@
|
|||||||
<string name="profiles">"프로필"</string>
|
<string name="profiles">"프로필"</string>
|
||||||
<string name="settings">"설정"</string>
|
<string name="settings">"설정"</string>
|
||||||
<string name="faq">"자주 묻는 질문"</string>
|
<string name="faq">"자주 묻는 질문"</string>
|
||||||
<string name="faq_url">"https://github.com/shadowsocks/shadowsocks-android/blob/master/.github/faq.md"</string>
|
|
||||||
<string name="about">"이 앱에 대하여"</string>
|
<string name="about">"이 앱에 대하여"</string>
|
||||||
<string name="about_title">"Shadowsocks %s"</string>
|
|
||||||
<string name="edit">"수정"</string>
|
<string name="edit">"수정"</string>
|
||||||
<string name="share">"공유"</string>
|
<string name="share">"공유"</string>
|
||||||
<string name="add_profile">"프로필 추가"</string>
|
<string name="add_profile">"프로필 추가"</string>
|
||||||
<string name="action_apply_all">"Apply Settings to All Profiles"</string>
|
|
||||||
<string name="action_export">"클립보드로 내보내기"</string>
|
<string name="action_export">"클립보드로 내보내기"</string>
|
||||||
<string name="action_import">"클립보드에서 불러오기"</string>
|
<string name="action_import">"클립보드에서 불러오기"</string>
|
||||||
<string name="action_export_msg">"성공적으로 내보냈습니다"</string>
|
<string name="action_export_msg">"성공적으로 내보냈습니다"</string>
|
||||||
@@ -102,34 +98,15 @@
|
|||||||
</plurals>
|
</plurals>
|
||||||
<string name="undo">"실행 취소"</string>
|
<string name="undo">"실행 취소"</string>
|
||||||
|
|
||||||
<!-- tasker -->
|
|
||||||
<string name="toggle_service_state">"Start the service"</string>
|
|
||||||
<string name="start_service_default">"Connect to the current server"</string>
|
|
||||||
<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 -->
|
<!-- status -->
|
||||||
<string name="sent">"송신:"</string>
|
<string name="sent">"송신:"</string>
|
||||||
<string name="received">"수신:"</string>
|
<string name="received">"수신:"</string>
|
||||||
<string name="connecting">"연결 중…"</string>
|
<string name="connecting">"연결 중…"</string>
|
||||||
<string name="vpn_connected">"연결 완료. 탭 하면 연결 상태를 검사합니다."</string>
|
<string name="vpn_connected">"연결 완료. 탭 하면 연결 상태를 검사합니다."</string>
|
||||||
<string name="not_connected">"Not connected"</string>
|
|
||||||
|
|
||||||
<!-- acl -->
|
<!-- acl -->
|
||||||
<string name="custom_rules">"사용자 정의 규칙"</string>
|
<string name="custom_rules">"사용자 정의 규칙"</string>
|
||||||
<string name="action_selection">"Selection…"</string>
|
<string name="acl_rule_templates_generic">"서브넷 혹은 호스트 이름 PCRE 패턴"</string>
|
||||||
<string name="action_add_rule">"Add rule(s)…"</string>
|
|
||||||
<string name="edit_rule">"Edit rule"</string>
|
|
||||||
<string name="route_entry_all">"All"</string>
|
|
||||||
<string name="route_entry_bypass_lan">"Bypass LAN"</string>
|
|
||||||
<string name="route_entry_bypass_chn">"Bypass mainland China"</string>
|
|
||||||
<string name="route_entry_bypass_lan_chn">"Bypass LAN & mainland China"</string>
|
|
||||||
<string name="route_entry_chinalist">"China List"</string>
|
|
||||||
<string name="proxied_apps_summary_v21">"Configure VPN mode for selected apps"</string>
|
|
||||||
|
|
||||||
<string name="acl_rule_templates_generic">"URL, 서브넷 혹은 호스트 이름 PCRE 패턴"</string>
|
|
||||||
<string name="acl_rule_templates_domain">"Domain name and all its subdomain names"</string>
|
|
||||||
|
|
||||||
<!-- plugin -->
|
<!-- plugin -->
|
||||||
<string name="plugin">"플러그인"</string>
|
<string name="plugin">"플러그인"</string>
|
||||||
@@ -139,21 +116,4 @@
|
|||||||
<string name="plugin_untrusted">"경고: 이 플러그인은 신뢰할 수 있는 출처에서 온 것이 아닌 것 같습니다"</string>
|
<string name="plugin_untrusted">"경고: 이 플러그인은 신뢰할 수 있는 출처에서 온 것이 아닌 것 같습니다"</string>
|
||||||
<string name="profile_plugin">"플러그인: %s"</string>
|
<string name="profile_plugin">"플러그인: %s"</string>
|
||||||
<string name="add_profile_scanner_permission_required">"QR 코드를 읽어 들이려면 카메라 권한이 필요합니다"</string>
|
<string name="add_profile_scanner_permission_required">"QR 코드를 읽어 들이려면 카메라 권한이 필요합니다"</string>
|
||||||
|
</resources>
|
||||||
<!-- notification category -->
|
|
||||||
<string name="service_vpn">"VPN Service"</string>
|
|
||||||
<string name="add_profile_methods_manual_settings">"Manual Settings"</string>
|
|
||||||
<string name="advanced">"Advanced"</string>
|
|
||||||
<string name="service_mode">"Service mode"</string>
|
|
||||||
<string name="service_mode_proxy">"Proxy only"</string>
|
|
||||||
<string name="service_mode_vpn">"VPN"</string>
|
|
||||||
<string name="service_mode_transproxy">"Transproxy"</string>
|
|
||||||
<string name="port_proxy">"SOCKS5 proxy port"</string>
|
|
||||||
<string name="port_local_dns">"Local DNS port"</string>
|
|
||||||
<string name="port_transproxy">"Transproxy port"</string>
|
|
||||||
<string name="service_proxy">"Proxy Service"</string>
|
|
||||||
<string name="service_transproxy">"Transproxy Service"</string>
|
|
||||||
<string name="vpn_permission_denied">"Permission denied to create a VPN service"</string>
|
|
||||||
<string name="auto_connect_summary_v24">"Enable Shadowsocks on startup. Recommended to use always-on VPN
|
|
||||||
instead"</string>
|
|
||||||
</resources>
|
|
||||||
@@ -1,15 +1,13 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">"Shadowsocks"</string>
|
|
||||||
<string name="quick_toggle">"Подключение"</string>
|
<string name="quick_toggle">"Подключение"</string>
|
||||||
|
|
||||||
<!-- misc -->
|
<!-- misc -->
|
||||||
<string name="profile">"Профиль"</string>
|
<string name="profile">"Профиль"</string>
|
||||||
<string name="profile_summary">"Переключить на другой профиль или добавить новые"</string>
|
<string name="profile_summary">"Переключить на другой профиль или добавить новые"</string>
|
||||||
<string name="remote_dns">"Удалённый DNS"</string>
|
<string name="remote_dns">"Удалённый DNS"</string>
|
||||||
<string name="stat_summary">"Отправлено: \t%3$s\t↑\t%1$s/s
|
<string name="stat_summary">"Отправлено: \t%3$s\t↑\t%1$s
|
||||||
Получено: \t%4$s\t↓\t%2$s/s"</string>
|
Получено: \t\t\t%4$s\t↓\t%2$s"</string>
|
||||||
|
|
||||||
<plurals name="bytes">
|
<plurals name="bytes">
|
||||||
<item quantity="one">"байт"</item>
|
<item quantity="one">"байт"</item>
|
||||||
<item quantity="few">"байта"</item>
|
<item quantity="few">"байта"</item>
|
||||||
@@ -27,11 +25,11 @@
|
|||||||
<string name="proxy_cat">"Настройки Сервера"</string>
|
<string name="proxy_cat">"Настройки Сервера"</string>
|
||||||
|
|
||||||
<!-- proxy category -->
|
<!-- proxy category -->
|
||||||
<string name="profile_name">"Имя Профиля"</string>
|
<string name="profile_name">"Имя профиля"</string>
|
||||||
<string name="proxy">"Сервер"</string>
|
<string name="proxy">"Сервер"</string>
|
||||||
<string name="remote_port">"Удалённый порт"</string>
|
<string name="remote_port">"Удалённый порт"</string>
|
||||||
<string name="sitekey">"Пароль"</string>
|
<string name="sitekey">"Пароль"</string>
|
||||||
<string name="enc_method">"Метод Шифрования"</string>
|
<string name="enc_method">"Метод шифрования"</string>
|
||||||
|
|
||||||
<!-- feature category -->
|
<!-- feature category -->
|
||||||
<string name="feature_cat">"Дополнительные Настройки"</string>
|
<string name="feature_cat">"Дополнительные Настройки"</string>
|
||||||
@@ -41,14 +39,12 @@
|
|||||||
<string name="ipv6_summary">"Перенаправлять трафик IPv6 на удалённый сервер"</string>
|
<string name="ipv6_summary">"Перенаправлять трафик IPv6 на удалённый сервер"</string>
|
||||||
<string name="route_list">"Маршрут"</string>
|
<string name="route_list">"Маршрут"</string>
|
||||||
<string name="route_entry_gfwlist">"Список GFW"</string>
|
<string name="route_entry_gfwlist">"Список GFW"</string>
|
||||||
|
<string name="proxied_apps">"Режим VPN для выбранных приложений"</string>
|
||||||
<string name="proxied_apps">"Прокси для выбранных приложений"</string>
|
<string name="proxied_apps_summary">"Выбрать приложения, для которых нужно использовать режим VPN"</string>
|
||||||
|
|
||||||
<string name="proxied_apps_summary">"Установить прокси для выбранных приложений, требует режим NAT под Android 4.x"</string>
|
|
||||||
<string name="on">"Вкл"</string>
|
<string name="on">"Вкл"</string>
|
||||||
<string name="bypass_apps">"В обход прокси"</string>
|
<string name="bypass_apps">"В обход прокси"</string>
|
||||||
<string name="bypass_apps_summary">"Включите эту опцию для работы выбранных приложений в обход прокси"</string>
|
<string name="bypass_apps_summary">"Включите эту опцию для работы выбранных приложений в обход прокси"</string>
|
||||||
<string name="auto_connect">"Авто Подключение"</string>
|
<string name="auto_connect">"Авто-подключение"</string>
|
||||||
<string name="auto_connect_summary">"Запускать Shadowsocks при включении"</string>
|
<string name="auto_connect_summary">"Запускать Shadowsocks при включении"</string>
|
||||||
<string name="tcp_fastopen_summary">"Переключение требует наличия ROOT прав"</string>
|
<string name="tcp_fastopen_summary">"Переключение требует наличия ROOT прав"</string>
|
||||||
<string name="tcp_fastopen_summary_unsupported">"Неподдерживаемая версия ядра: %s < 3.7.1"</string>
|
<string name="tcp_fastopen_summary_unsupported">"Неподдерживаемая версия ядра: %s < 3.7.1"</string>
|
||||||
@@ -61,9 +57,8 @@
|
|||||||
<string name="service_failed">"Ошибка при подключении к удалённому серверу"</string>
|
<string name="service_failed">"Ошибка при подключении к удалённому серверу"</string>
|
||||||
<string name="stop">"Остановить"</string>
|
<string name="stop">"Остановить"</string>
|
||||||
<string name="stopping">"Останавливается…"</string>
|
<string name="stopping">"Останавливается…"</string>
|
||||||
<string name="vpn_error">"%s"</string>
|
|
||||||
<string name="reboot_required">"Не удалось запустить службу VPN. Возможно, требуется перезагрузить ваше устройство."</string>
|
<string name="reboot_required">"Не удалось запустить службу VPN. Возможно, требуется перезагрузить ваше устройство."</string>
|
||||||
<string name="profile_invalid_input">"No valid profile data found."</string>
|
<string name="profile_invalid_input">"Не найдено действительных данных профиля."</string>
|
||||||
|
|
||||||
<!-- alert category -->
|
<!-- alert category -->
|
||||||
<string name="yes">"Да"</string>
|
<string name="yes">"Да"</string>
|
||||||
@@ -79,13 +74,13 @@
|
|||||||
<!-- menu category -->
|
<!-- menu category -->
|
||||||
<string name="profiles">"Профили"</string>
|
<string name="profiles">"Профили"</string>
|
||||||
<string name="settings">"Настройки"</string>
|
<string name="settings">"Настройки"</string>
|
||||||
<string name="faq">"FAQ"</string>
|
<string name="faq">"ЧаВо"</string>
|
||||||
<string name="faq_url">"https://github.com/shadowsocks/shadowsocks-android/blob/master/.github/faq.md"</string>
|
<string name="faq_url">"https://github.com/shadowsocks/shadowsocks-android/blob/master/.github/faq.ru.md"</string>
|
||||||
<string name="about">"О приложении"</string>
|
<string name="about">"О приложении"</string>
|
||||||
<string name="about_title">"Shadowsocks %s"</string>
|
<string name="about_title">"Shadowsocks %s"</string>
|
||||||
<string name="edit">"Изменить"</string>
|
<string name="edit">"Изменить"</string>
|
||||||
<string name="share">"Поделиться"</string>
|
<string name="share">"Поделиться"</string>
|
||||||
<string name="add_profile">"Добавить Профиль"</string>
|
<string name="add_profile">"Добавить профиль"</string>
|
||||||
<string name="action_apply_all">"Применить настройки для всех профилей"</string>
|
<string name="action_apply_all">"Применить настройки для всех профилей"</string>
|
||||||
<string name="action_export">"Экспортировать в буфер обмена"</string>
|
<string name="action_export">"Экспортировать в буфер обмена"</string>
|
||||||
<string name="action_import">"Импортировать из буфера обмена"</string>
|
<string name="action_import">"Импортировать из буфера обмена"</string>
|
||||||
@@ -101,7 +96,7 @@
|
|||||||
<string name="delete">"Удалить"</string>
|
<string name="delete">"Удалить"</string>
|
||||||
<string name="delete_confirm_prompt">"Вы уверены, что хотите удалить этот профиль?"</string>
|
<string name="delete_confirm_prompt">"Вы уверены, что хотите удалить этот профиль?"</string>
|
||||||
<string name="share_qr_nfc">"QR-код/NFC"</string>
|
<string name="share_qr_nfc">"QR-код/NFC"</string>
|
||||||
<string name="add_profile_dialog">"Добавить этот Профиль Shadowsocks?"</string>
|
<string name="add_profile_dialog">"Добавить этот профиль Shadowsocks?"</string>
|
||||||
<string name="add_profile_methods_scan_qr_code">"Сканировать QR-код"</string>
|
<string name="add_profile_methods_scan_qr_code">"Сканировать QR-код"</string>
|
||||||
<plurals name="removed">
|
<plurals name="removed">
|
||||||
<item quantity="one">"Удалено %d элементов"</item>
|
<item quantity="one">"Удалено %d элементов"</item>
|
||||||
@@ -135,10 +130,7 @@
|
|||||||
<string name="route_entry_bypass_chn">"Все, кроме Китая"</string>
|
<string name="route_entry_bypass_chn">"Все, кроме Китая"</string>
|
||||||
<string name="route_entry_bypass_lan_chn">"Все, кроме LAN и Китая"</string>
|
<string name="route_entry_bypass_lan_chn">"Все, кроме LAN и Китая"</string>
|
||||||
<string name="route_entry_chinalist">"Список Китай"</string>
|
<string name="route_entry_chinalist">"Список Китай"</string>
|
||||||
|
<string name="acl_rule_templates_generic">"Подсеть или имя хоста, записанное регулярным выражением (PCRE)"</string>
|
||||||
<string name="proxied_apps_summary_v21">"Установить прокси для выбранных приложений"</string>
|
|
||||||
|
|
||||||
<string name="acl_rule_templates_generic">"URL/Подсеть/Регулярное выражение (PCRE) имени хоста"</string>
|
|
||||||
<string name="acl_rule_templates_domain">"Доменное имя и все его поддомены"</string>
|
<string name="acl_rule_templates_domain">"Доменное имя и все его поддомены"</string>
|
||||||
|
|
||||||
<!-- plugin -->
|
<!-- plugin -->
|
||||||
@@ -151,19 +143,21 @@
|
|||||||
<string name="add_profile_scanner_permission_required">"Разрешение камеры требуется для сканирования QR код."</string>
|
<string name="add_profile_scanner_permission_required">"Разрешение камеры требуется для сканирования QR код."</string>
|
||||||
|
|
||||||
<!-- notification category -->
|
<!-- notification category -->
|
||||||
<string name="service_vpn">"VPN Service"</string>
|
<string name="service_vpn">"Служба VPN"</string>
|
||||||
<string name="add_profile_methods_manual_settings">"Manual Settings"</string>
|
<string name="add_profile_methods_manual_settings">"Ручные настройки"</string>
|
||||||
<string name="advanced">"Advanced"</string>
|
<string name="advanced">"Дополнительно"</string>
|
||||||
<string name="service_mode">"Service mode"</string>
|
<string name="service_mode">"Режим"</string>
|
||||||
<string name="service_mode_proxy">"Proxy only"</string>
|
<string name="service_mode_proxy">"Только прокси"</string>
|
||||||
<string name="service_mode_vpn">"VPN"</string>
|
<string name="service_mode_transproxy">"Прозрачный прокси"</string>
|
||||||
<string name="service_mode_transproxy">"Transproxy"</string>
|
<string name="port_proxy">"Порт SOCKS5 прокси"</string>
|
||||||
<string name="port_proxy">"SOCKS5 proxy port"</string>
|
<string name="port_local_dns">"Локальный порт DNS"</string>
|
||||||
<string name="port_local_dns">"Local DNS port"</string>
|
<string name="port_transproxy">"Порт прозрачного прокси"</string>
|
||||||
<string name="port_transproxy">"Transproxy port"</string>
|
<string name="service_proxy">"Служба прокси"</string>
|
||||||
<string name="service_proxy">"Proxy Service"</string>
|
<string name="service_transproxy">"Служба прозрачный прокси"</string>
|
||||||
<string name="service_transproxy">"Transproxy Service"</string>
|
<string name="vpn_permission_denied">"Нет разрешения на создание VPN соединения"</string>
|
||||||
<string name="vpn_permission_denied">"Permission denied to create a VPN service"</string>
|
<string name="auto_connect_summary_v24">"Включить Shadowsocks во время запуска. Лучше использовать режим постоянной VPN."</string>
|
||||||
<string name="auto_connect_summary_v24">"Enable Shadowsocks on startup. Recommended to use always-on VPN
|
<string name="speed">"%s/с"</string>
|
||||||
instead"</string>
|
<string name="direct_boot_aware">"Непосредственная загрузка"</string>
|
||||||
</resources>
|
<string name="direct_boot_aware_summary">"Позволить Shadowsocks запускаться до того, как устройство будет разблокировано (данные выбранного профиля будут хуже защищены)"</string>
|
||||||
|
<string name="acl_rule_online_config">"URL конфигурации"</string>
|
||||||
|
</resources>
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<dimen name="fab_margin_top">-28dp</dimen>
|
|
||||||
</resources>
|
|
||||||
@@ -1,27 +1,19 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<string name="app_name">"影梭"</string>
|
<string name="app_name">"影梭"</string>
|
||||||
|
|
||||||
<string name="quick_toggle">"开关"</string>
|
<string name="quick_toggle">"开关"</string>
|
||||||
|
|
||||||
<!-- misc -->
|
<!-- misc -->
|
||||||
<string name="profile">"配置文件"</string>
|
<string name="profile">"配置文件"</string>
|
||||||
|
|
||||||
<string name="profile_summary">"新建或切换到其他配置文件"</string>
|
<string name="profile_summary">"新建或切换到其他配置文件"</string>
|
||||||
|
|
||||||
<string name="remote_dns">"远程 DNS"</string>
|
<string name="remote_dns">"远程 DNS"</string>
|
||||||
|
<string name="stat_summary">"上传: \t%3$s\t↑\t%1$s
|
||||||
<string name="stat_summary">"上传: \t%3$s\t↑\t%1$s/s
|
下载: \t%4$s\t↓\t%2$s"</string>
|
||||||
下载: \t%4$s\t↓\t%2$s/s"</string>
|
|
||||||
|
|
||||||
<string name="connection_test_pending">"检查网络连接"</string>
|
<string name="connection_test_pending">"检查网络连接"</string>
|
||||||
<string name="connection_test_testing">"测试中…"</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_error">"失败:%s"</string>
|
<string name="connection_test_error">"失败:%s"</string>
|
||||||
<string name="connection_test_fail">"无互联网连接"</string>
|
<string name="connection_test_fail">"无互联网连接"</string>
|
||||||
|
|
||||||
<string name="connection_test_error_status_code">"状态码无效(#%d)"</string>
|
<string name="connection_test_error_status_code">"状态码无效(#%d)"</string>
|
||||||
|
|
||||||
<!-- proxy category -->
|
<!-- proxy category -->
|
||||||
@@ -29,7 +21,6 @@
|
|||||||
|
|
||||||
<!-- proxy category -->
|
<!-- proxy category -->
|
||||||
<string name="profile_name">"配置名称"</string>
|
<string name="profile_name">"配置名称"</string>
|
||||||
|
|
||||||
<string name="proxy">"服务器"</string>
|
<string name="proxy">"服务器"</string>
|
||||||
<string name="remote_port">"远程端口"</string>
|
<string name="remote_port">"远程端口"</string>
|
||||||
<string name="sitekey">"密码"</string>
|
<string name="sitekey">"密码"</string>
|
||||||
@@ -44,7 +35,6 @@
|
|||||||
<string name="route_list">"路由"</string>
|
<string name="route_list">"路由"</string>
|
||||||
<string name="route_entry_gfwlist">"GFW 列表"</string>
|
<string name="route_entry_gfwlist">"GFW 列表"</string>
|
||||||
<string name="proxied_apps">"分应用 VPN"</string>
|
<string name="proxied_apps">"分应用 VPN"</string>
|
||||||
|
|
||||||
<string name="proxied_apps_summary">"允许部分应用绕过 VPN"</string>
|
<string name="proxied_apps_summary">"允许部分应用绕过 VPN"</string>
|
||||||
<string name="on">"启用"</string>
|
<string name="on">"启用"</string>
|
||||||
<string name="bypass_apps">"绕行模式"</string>
|
<string name="bypass_apps">"绕行模式"</string>
|
||||||
@@ -81,7 +71,6 @@
|
|||||||
<string name="profiles">"配置文件"</string>
|
<string name="profiles">"配置文件"</string>
|
||||||
<string name="settings">"设置选项"</string>
|
<string name="settings">"设置选项"</string>
|
||||||
<string name="faq">"常见问题"</string>
|
<string name="faq">"常见问题"</string>
|
||||||
<string name="faq_url">"https://github.com/shadowsocks/shadowsocks-android/blob/master/.github/faq.md"</string>
|
|
||||||
<string name="about">"关于"</string>
|
<string name="about">"关于"</string>
|
||||||
<string name="about_title">"影梭 (Shadowsocks) %s"</string>
|
<string name="about_title">"影梭 (Shadowsocks) %s"</string>
|
||||||
<string name="edit">"编辑"</string>
|
<string name="edit">"编辑"</string>
|
||||||
@@ -133,12 +122,8 @@
|
|||||||
<string name="route_entry_bypass_chn">"绕过中国大陆地址"</string>
|
<string name="route_entry_bypass_chn">"绕过中国大陆地址"</string>
|
||||||
<string name="route_entry_bypass_lan_chn">"绕过局域网及中国大陆地址"</string>
|
<string name="route_entry_bypass_lan_chn">"绕过局域网及中国大陆地址"</string>
|
||||||
<string name="route_entry_chinalist">"仅代理中国大陆地址"</string>
|
<string name="route_entry_chinalist">"仅代理中国大陆地址"</string>
|
||||||
|
<string name="acl_rule_templates_generic">"子网/域名 PCRE 正则表达式"</string>
|
||||||
<string name="proxied_apps_summary_v21">"为应用程序分别设置代理"</string>
|
|
||||||
|
|
||||||
<string name="acl_rule_templates_generic">"URL/子网/域名 PCRE 正则表达式"</string>
|
|
||||||
<string name="acl_rule_templates_domain">"域名及其子域名"</string>
|
<string name="acl_rule_templates_domain">"域名及其子域名"</string>
|
||||||
<string name="acl_rule_online_config">配置文件地址</string>
|
|
||||||
|
|
||||||
<!-- plugin -->
|
<!-- plugin -->
|
||||||
<string name="plugin">"插件"</string>
|
<string name="plugin">"插件"</string>
|
||||||
@@ -155,7 +140,6 @@
|
|||||||
<string name="advanced">"高级选项"</string>
|
<string name="advanced">"高级选项"</string>
|
||||||
<string name="service_mode">"服务模式"</string>
|
<string name="service_mode">"服务模式"</string>
|
||||||
<string name="service_mode_proxy">"仅代理"</string>
|
<string name="service_mode_proxy">"仅代理"</string>
|
||||||
<string name="service_mode_vpn">"VPN"</string>
|
|
||||||
<string name="service_mode_transproxy">"透明代理"</string>
|
<string name="service_mode_transproxy">"透明代理"</string>
|
||||||
<string name="port_proxy">"SOCKS5 代理端口"</string>
|
<string name="port_proxy">"SOCKS5 代理端口"</string>
|
||||||
<string name="port_local_dns">"本地 DNS 端口"</string>
|
<string name="port_local_dns">"本地 DNS 端口"</string>
|
||||||
@@ -164,4 +148,7 @@
|
|||||||
<string name="service_transproxy">"透明代理模式"</string>
|
<string name="service_transproxy">"透明代理模式"</string>
|
||||||
<string name="vpn_permission_denied">"创建 VPN 服务权限不足"</string>
|
<string name="vpn_permission_denied">"创建 VPN 服务权限不足"</string>
|
||||||
<string name="auto_connect_summary_v24">"允许 Shadowsocks 随系统启动,建议使用始终开启的 VPN"</string>
|
<string name="auto_connect_summary_v24">"允许 Shadowsocks 随系统启动,建议使用始终开启的 VPN"</string>
|
||||||
</resources>
|
<string name="direct_boot_aware">"直接启动"</string>
|
||||||
|
<string name="direct_boot_aware_summary">"允许在设备解锁前启动服务(选中的配置信息会不那么安全)"</string>
|
||||||
|
<string name="acl_rule_online_config">"在线规则文件 URL"</string>
|
||||||
|
</resources>
|
||||||
@@ -37,10 +37,8 @@
|
|||||||
<string name="ipv6_summary">"向遠端重新導向 IPv6 流量"</string>
|
<string name="ipv6_summary">"向遠端重新導向 IPv6 流量"</string>
|
||||||
<string name="route_list">"路由"</string>
|
<string name="route_list">"路由"</string>
|
||||||
<string name="route_entry_gfwlist">"GFW List"</string>
|
<string name="route_entry_gfwlist">"GFW List"</string>
|
||||||
|
<string name="proxied_apps">"個別應用程式的 VPN"</string>
|
||||||
<string name="proxied_apps">"個別應用程式的 Proxy"</string>
|
<string name="proxied_apps_summary">"為已選擇的應用程式設定 VPN"</string>
|
||||||
|
|
||||||
<string name="proxied_apps_summary">"為已選擇的應用程式設定 Proxy,在 Android 4.X 以下需要開啟 NAT 模式"</string>
|
|
||||||
<string name="on">"開"</string>
|
<string name="on">"開"</string>
|
||||||
<string name="bypass_apps">"略過模式"</string>
|
<string name="bypass_apps">"略過模式"</string>
|
||||||
<string name="bypass_apps_summary">"啟用此選項,會略過已選擇的應用程式"</string>
|
<string name="bypass_apps_summary">"啟用此選項,會略過已選擇的應用程式"</string>
|
||||||
@@ -57,7 +55,6 @@
|
|||||||
<string name="service_failed">"連線至遠端伺服器失敗"</string>
|
<string name="service_failed">"連線至遠端伺服器失敗"</string>
|
||||||
<string name="stop">"停止"</string>
|
<string name="stop">"停止"</string>
|
||||||
<string name="stopping">"關閉中…"</string>
|
<string name="stopping">"關閉中…"</string>
|
||||||
<string name="vpn_error">"%s"</string>
|
|
||||||
<string name="reboot_required">"VPN 服務啟動失敗。您或許需要重新啟動您的裝置。"</string>
|
<string name="reboot_required">"VPN 服務啟動失敗。您或許需要重新啟動您的裝置。"</string>
|
||||||
<string name="profile_invalid_input">"未找到有效的設定檔資料。"</string>
|
<string name="profile_invalid_input">"未找到有效的設定檔資料。"</string>
|
||||||
|
|
||||||
@@ -76,7 +73,6 @@
|
|||||||
<string name="profiles">"設定檔"</string>
|
<string name="profiles">"設定檔"</string>
|
||||||
<string name="settings">"設定"</string>
|
<string name="settings">"設定"</string>
|
||||||
<string name="faq">"常見問題"</string>
|
<string name="faq">"常見問題"</string>
|
||||||
<string name="faq_url">"https://github.com/shadowsocks/shadowsocks-android/blob/master/.github/faq.md"</string>
|
|
||||||
<string name="about">"關於"</string>
|
<string name="about">"關於"</string>
|
||||||
<string name="about_title">"Shadowsocks %s"</string>
|
<string name="about_title">"Shadowsocks %s"</string>
|
||||||
<string name="edit">"編輯"</string>
|
<string name="edit">"編輯"</string>
|
||||||
@@ -128,12 +124,8 @@
|
|||||||
<string name="route_entry_bypass_chn">"略過中國大陸"</string>
|
<string name="route_entry_bypass_chn">"略過中國大陸"</string>
|
||||||
<string name="route_entry_bypass_lan_chn">"略過區域網路及中國大陸"</string>
|
<string name="route_entry_bypass_lan_chn">"略過區域網路及中國大陸"</string>
|
||||||
<string name="route_entry_chinalist">"China List"</string>
|
<string name="route_entry_chinalist">"China List"</string>
|
||||||
|
<string name="acl_rule_templates_generic">"子網路/主機名稱 PCRE 模式"</string>
|
||||||
<string name="proxied_apps_summary_v21">"為已選擇的應用程式設定 Proxy"</string>
|
|
||||||
|
|
||||||
<string name="acl_rule_templates_generic">"URL/子網路/主機名稱 PCRE 模式"</string>
|
|
||||||
<string name="acl_rule_templates_domain">"網域及其所有子網域"</string>
|
<string name="acl_rule_templates_domain">"網域及其所有子網域"</string>
|
||||||
<string name="acl_rule_online_config">配置文件地址</string>
|
|
||||||
|
|
||||||
<!-- plugin -->
|
<!-- plugin -->
|
||||||
<string name="plugin">"外掛程式"</string>
|
<string name="plugin">"外掛程式"</string>
|
||||||
@@ -150,7 +142,6 @@
|
|||||||
<string name="advanced">"高級"</string>
|
<string name="advanced">"高級"</string>
|
||||||
<string name="service_mode">"服務模式"</string>
|
<string name="service_mode">"服務模式"</string>
|
||||||
<string name="service_mode_proxy">"仅代理"</string>
|
<string name="service_mode_proxy">"仅代理"</string>
|
||||||
<string name="service_mode_vpn">"VPN"</string>
|
|
||||||
<string name="service_mode_transproxy">"透明代理"</string>
|
<string name="service_mode_transproxy">"透明代理"</string>
|
||||||
<string name="port_proxy">"SOCKS5 代理連接埠"</string>
|
<string name="port_proxy">"SOCKS5 代理連接埠"</string>
|
||||||
<string name="port_local_dns">"本地 DNS 連接埠"</string>
|
<string name="port_local_dns">"本地 DNS 連接埠"</string>
|
||||||
@@ -159,4 +150,4 @@
|
|||||||
<string name="service_transproxy">"透明代理服務"</string>
|
<string name="service_transproxy">"透明代理服務"</string>
|
||||||
<string name="vpn_permission_denied">"没有權限創建 VPN 服務"</string>
|
<string name="vpn_permission_denied">"没有權限創建 VPN 服務"</string>
|
||||||
<string name="auto_connect_summary_v24">"允許 Shadowsocks 隨系統啟動,建議使用始終開啟的 VPN"</string>
|
<string name="auto_connect_summary_v24">"允許 Shadowsocks 隨系統啟動,建議使用始終開啟的 VPN"</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -4,5 +4,4 @@
|
|||||||
<dimen name="qr_code_size">250dp</dimen>
|
<dimen name="qr_code_size">250dp</dimen>
|
||||||
<dimen name="profile_padding">8dp</dimen>
|
<dimen name="profile_padding">8dp</dimen>
|
||||||
<dimen name="bottom_sheet_padding">8dp</dimen>
|
<dimen name="bottom_sheet_padding">8dp</dimen>
|
||||||
<dimen name="fab_margin_top">-44dp</dimen>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
<AutoSummaryEditTextPreference
|
<AutoSummaryEditTextPreference
|
||||||
android:key="proxy"
|
android:key="proxy"
|
||||||
app:pref_summaryHasText="%s"
|
app:pref_summaryHasText="%s"
|
||||||
|
android:singleLine="true"
|
||||||
android:title="@string/proxy"/>
|
android:title="@string/proxy"/>
|
||||||
<AutoSummaryEditTextPreference
|
<AutoSummaryEditTextPreference
|
||||||
android:key="remotePortNum"
|
android:key="remotePortNum"
|
||||||
@@ -25,6 +26,7 @@
|
|||||||
app:pref_summaryPasswordSubstituteLength="0"
|
app:pref_summaryPasswordSubstituteLength="0"
|
||||||
android:key="sitekey"
|
android:key="sitekey"
|
||||||
app:pref_summaryHasText="%s"
|
app:pref_summaryHasText="%s"
|
||||||
|
android:singleLine="true"
|
||||||
android:title="@string/sitekey"/>
|
android:title="@string/sitekey"/>
|
||||||
<SimpleMenuPreference
|
<SimpleMenuPreference
|
||||||
android:key="encMethod"
|
android:key="encMethod"
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api "com.android.support:preference-v7:$supportLibraryVersion"
|
|
||||||
api "com.android.support:preference-v14:$supportLibraryVersion"
|
api "com.android.support:preference-v14:$supportLibraryVersion"
|
||||||
api "com.takisoft.fix:preference-v7:$takisoftFixVersion"
|
api "com.takisoft.fix:preference-v7:$takisoftFixVersion"
|
||||||
api "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlinVersion"
|
api "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlinVersion"
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:background="?attr/colorPrimary"
|
android:background="?attr/colorPrimary"
|
||||||
android:elevation="4dp"
|
android:elevation="4dp"
|
||||||
|
android:touchscreenBlocksFocus="false"
|
||||||
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||||
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
|
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
|
||||||
android:id="@+id/toolbar" />
|
android:id="@+id/toolbar" />
|
||||||
|
|||||||
@@ -1,15 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<!-- proxy category -->
|
|
||||||
<string name="proxy_cat">"サーバー設定"</string>
|
<string name="proxy_cat">"サーバー設定"</string>
|
||||||
|
<string name="feature_cat">"機能設定"</string>
|
||||||
<!-- feature category -->
|
<string name="unsaved_changes_prompt">"変更は保存されておりません、保存しますか?"</string>
|
||||||
<string name="feature_cat">"ファンクション設定"</string>
|
|
||||||
|
|
||||||
<!-- alert category -->
|
|
||||||
<string name="yes">"はい"</string>
|
<string name="yes">"はい"</string>
|
||||||
<string name="no">"いいえ"</string>
|
<string name="no">"いいえ"</string>
|
||||||
<string name="unsaved_changes_prompt">"変更は適応されておりません、保存しますか?"</string>
|
<string name="apply">"適応"</string>
|
||||||
<string name="apply">"適用"</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,15 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
<string name="proxy_cat">"Настройки сервера"</string>
|
||||||
<!-- proxy category -->
|
<string name="feature_cat">"Настройки опций"</string>
|
||||||
<string name="proxy_cat">"Настройки Сервера"</string>
|
<string name="unsaved_changes_prompt">"Сохранить изменения?"</string>
|
||||||
|
|
||||||
<!-- feature category -->
|
|
||||||
<string name="feature_cat">"Дополнительные Настройки"</string>
|
|
||||||
|
|
||||||
<!-- alert category -->
|
|
||||||
<string name="yes">"Да"</string>
|
<string name="yes">"Да"</string>
|
||||||
<string name="no">"Нет"</string>
|
<string name="no">"Нет"</string>
|
||||||
<string name="unsaved_changes_prompt">"Изменения не сохранены. Сохранить?"</string>
|
|
||||||
<string name="apply">"Применить"</string>
|
<string name="apply">"Применить"</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,15 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<!-- proxy category -->
|
|
||||||
<string name="proxy_cat">"服务器设置"</string>
|
<string name="proxy_cat">"服务器设置"</string>
|
||||||
|
|
||||||
<!-- feature category -->
|
|
||||||
<string name="feature_cat">"功能设置"</string>
|
<string name="feature_cat">"功能设置"</string>
|
||||||
|
<string name="unsaved_changes_prompt">"是否要保存修改?"</string>
|
||||||
<!-- alert category -->
|
|
||||||
<string name="yes">"是"</string>
|
<string name="yes">"是"</string>
|
||||||
<string name="no">"否"</string>
|
<string name="no">"否"</string>
|
||||||
<string name="unsaved_changes_prompt">"保存修改吗?"</string>
|
|
||||||
<string name="apply">"应用"</string>
|
<string name="apply">"应用"</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
release=$1
|
||||||
|
cp mobile/build/outputs/apk/release/mobile-armeabi-v7a-release.apk shadowsocks-armeabi-v7a-${release}.apk
|
||||||
|
cp mobile/build/outputs/apk/release/mobile-arm64-v8a-release.apk shadowsocks-arm64-v8a-${release}.apk
|
||||||
|
cp mobile/build/outputs/apk/release/mobile-x86-release.apk shadowsocks-x86-${release}.apk
|
||||||