Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97c6ff95cd | ||
|
|
971ef22186 | ||
|
|
c35a92a927 | ||
|
|
c05a63a75b | ||
|
|
6074a99eb6 | ||
|
|
e52719d1be | ||
|
|
cfaaaf5341 | ||
|
|
4a4d3b11fb | ||
|
|
3538caa80d | ||
|
|
ae30c218e9 | ||
|
|
86e93ffa2d | ||
|
|
acd89cc999 | ||
|
|
382af46d91 | ||
|
|
415a9f6847 | ||
|
|
91a069bc44 |
@@ -20,18 +20,8 @@ before_install:
|
|||||||
- export PATH=${PATH}:${ANDROID_NDK_HOME}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools
|
- export PATH=${PATH}:${ANDROID_NDK_HOME}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools
|
||||||
- echo "y" | android update sdk --filter tools,platform-tools,build-tools-20.0.0,android-19,extra-google-m2repository --no-ui --no-https -a
|
- echo "y" | android update sdk --filter tools,platform-tools,build-tools-20.0.0,android-19,extra-google-m2repository --no-ui --no-https -a
|
||||||
- echo "y" | android update sdk --filter extra-android-m2repository --no-ui --no-https -a
|
- echo "y" | android update sdk --filter extra-android-m2repository --no-ui --no-https -a
|
||||||
install:
|
|
||||||
- gem install --version 0.8.9 faraday
|
|
||||||
- gem install travis-artifacts
|
|
||||||
script:
|
script:
|
||||||
- ./build-ndk.sh
|
- ./build-ndk.sh
|
||||||
- cp local.properties.travis local.properties
|
- cp local.properties.travis local.properties
|
||||||
- sbt clean android:package-release
|
- sbt android:package-release
|
||||||
after_success:
|
- exit 0
|
||||||
- ./deploy target/android-bin shadowsocks-release.apk
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
- "ARTIFACTS_AWS_REGION=us-east-1"
|
|
||||||
- "ARTIFACTS_S3_BUCKET=travis-nightly"
|
|
||||||
- secure: "GkAdnMh07id2VKhpCW16lE73A0LK2Jsk3hzkFvdx76JKW8FjLgaimLJ2T/+i\nxFfDw8XBinLE09dqg8JxSNS6JbLHLcav8P3yJIlzFh1NqfJABU9U4I8atb6P\nITSdSo9nb3LX6sB8SOU0nqXb5U+nj7jiekQqiBhmEmu6iDmMtfU="
|
|
||||||
- secure: "eCh5BjCFccp+sB/FIrjsmxJU4475D4qiWvDV++khcIHLel6lgUjDX18ImBlJ\n+IdiCKxvR6EpRDV1Cs4gJ2jZEAV0PbojQMoQOXbs1FLggM8RRq/Re1qWQFq7\nWkBRjjr8w8ddjJZHRo459cTUvgvD7krhp07coabAnEahDaGWSUo="
|
|
||||||
|
|||||||
@@ -1,38 +1,28 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Target 9
|
function try () {
|
||||||
cp jni/Application.mk.9 jni/Application.mk
|
"$@" || exit -1
|
||||||
ndk-build clean
|
}
|
||||||
ndk-build
|
|
||||||
rm -rf src/main/assets/armeabi
|
# Build
|
||||||
|
try ndk-build clean
|
||||||
|
try ndk-build
|
||||||
|
|
||||||
|
# copy executables
|
||||||
rm -rf src/main/assets/armeabi-v7a
|
rm -rf src/main/assets/armeabi-v7a
|
||||||
rm -rf src/main/assets/x86
|
rm -rf src/main/assets/x86
|
||||||
mkdir -p src/main/assets/armeabi
|
|
||||||
mkdir -p src/main/assets/armeabi-v7a
|
mkdir -p src/main/assets/armeabi-v7a
|
||||||
mkdir -p src/main/assets/x86
|
mkdir -p src/main/assets/x86
|
||||||
for app in pdnsd redsocks
|
for app in pdnsd redsocks
|
||||||
do
|
do
|
||||||
mv libs/armeabi/$app src/main/assets/armeabi/
|
try mv libs/armeabi-v7a/$app src/main/assets/armeabi-v7a/
|
||||||
mv libs/armeabi-v7a/$app src/main/assets/armeabi-v7a/
|
try mv libs/x86/$app src/main/assets/x86/
|
||||||
mv libs/x86/$app src/main/assets/x86/
|
|
||||||
done
|
|
||||||
rm -rf src/main/jni
|
|
||||||
mv libs src/main/jni
|
|
||||||
|
|
||||||
# Target 16
|
|
||||||
cp jni/Application.mk.16 jni/Application.mk
|
|
||||||
ndk-build clean
|
|
||||||
ndk-build
|
|
||||||
rm -rf src/main/assets/api-16/armeabi
|
|
||||||
rm -rf src/main/assets/api-16/armeabi-v7a
|
|
||||||
rm -rf src/main/assets/api-16/x86
|
|
||||||
mkdir -p src/main/assets/api-16/armeabi
|
|
||||||
mkdir -p src/main/assets/api-16/armeabi-v7a
|
|
||||||
mkdir -p src/main/assets/api-16/x86
|
|
||||||
for app in pdnsd redsocks
|
|
||||||
do
|
|
||||||
mv libs/armeabi/$app src/main/assets/api-16/armeabi/
|
|
||||||
mv libs/armeabi-v7a/$app src/main/assets/api-16/armeabi-v7a/
|
|
||||||
mv libs/x86/$app src/main/assets/api-16/x86/
|
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# copy libraries
|
||||||
|
rm -rf src/main/jni/armeabi-v7a
|
||||||
|
rm -rf src/main/jni/x86
|
||||||
|
mkdir -p src/main/jni/armeabi-v7a
|
||||||
|
mkdir -p src/main/jni/x86
|
||||||
|
try mv libs/armeabi-v7a/*.so src/main/jni/armeabi-v7a/
|
||||||
|
try mv libs/x86/*.so src/main/jni/x86/
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ resolvers += "JRAF" at "http://JRAF.org/static/maven/2"
|
|||||||
resolvers += "madeye private releases" at "http://madeye-maven-repository.googlecode.com/git/"
|
resolvers += "madeye private releases" at "http://madeye-maven-repository.googlecode.com/git/"
|
||||||
|
|
||||||
libraryDependencies ++= Seq(
|
libraryDependencies ++= Seq(
|
||||||
"com.google.android" % "analytics" % "3.01",
|
|
||||||
"dnsjava" % "dnsjava" % "2.1.5",
|
"dnsjava" % "dnsjava" % "2.1.5",
|
||||||
"org.scalaj" %% "scalaj-http" % "0.3.10",
|
"org.scalaj" %% "scalaj-http" % "0.3.10",
|
||||||
"commons-net" % "commons-net" % "3.3",
|
"commons-net" % "commons-net" % "3.3",
|
||||||
@@ -23,15 +22,13 @@ libraryDependencies ++= Seq(
|
|||||||
)
|
)
|
||||||
|
|
||||||
libraryDependencies ++= Seq(
|
libraryDependencies ++= Seq(
|
||||||
aar("com.actionbarsherlock" % "actionbarsherlock" % "4.4.0") exclude("com.google.android", "support-v4"),
|
|
||||||
"net.simonvt.menudrawer" % "menudrawer" % "3.0.6",
|
"net.simonvt.menudrawer" % "menudrawer" % "3.0.6",
|
||||||
"org.jraf" % "android-switch-backport" % "1.3.1",
|
"com.google.android.gms" % "play-services" % "5.0.89",
|
||||||
"com.google.android.gms" % "play-services" % "4.4.52",
|
|
||||||
"com.android.support" % "support-v4" % "19.1.0"
|
"com.android.support" % "support-v4" % "19.1.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
libraryDependencies ++= Seq(
|
libraryDependencies ++= Seq(
|
||||||
"de.keyboardsurfer.android.widget" % "crouton" % "1.8.1" exclude("com.google.android", "support-v4"),
|
"de.keyboardsurfer.android.widget" % "crouton" % "1.8.4" exclude("com.google.android", "support-v4"),
|
||||||
"com.nostra13.universalimageloader" % "universal-image-loader" % "1.8.4",
|
"com.nostra13.universalimageloader" % "universal-image-loader" % "1.8.4",
|
||||||
"com.j256.ormlite" % "ormlite-core" % "4.47",
|
"com.j256.ormlite" % "ormlite-core" % "4.47",
|
||||||
"com.j256.ormlite" % "ormlite-android" % "4.47"
|
"com.j256.ormlite" % "ormlite-android" % "4.47"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
APP_ABI := armeabi armeabi-v7a x86
|
APP_ABI := armeabi-v7a x86
|
||||||
APP_PLATFORM := android-16
|
APP_PLATFORM := android-16
|
||||||
APP_STL := stlport_static
|
APP_STL := stlport_static
|
||||||
NDK_TOOLCHAIN_VERSION := 4.8
|
NDK_TOOLCHAIN_VERSION := 4.8
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
APP_ABI := armeabi armeabi-v7a x86
|
|
||||||
APP_PLATFORM := android-9
|
|
||||||
APP_STL := stlport_static
|
|
||||||
NDK_TOOLCHAIN_VERSION := 4.8
|
|
||||||
@@ -21,11 +21,11 @@ jstring Java_com_github_shadowsocks_system_getabi(JNIEnv *env, jobject thiz) {
|
|||||||
} else if (family == ANDROID_CPU_FAMILY_MIPS) {
|
} else if (family == ANDROID_CPU_FAMILY_MIPS) {
|
||||||
abi = "mips";
|
abi = "mips";
|
||||||
} else if (family == ANDROID_CPU_FAMILY_ARM) {
|
} else if (family == ANDROID_CPU_FAMILY_ARM) {
|
||||||
if (features & ANDROID_CPU_ARM_FEATURE_ARMv7) {
|
// if (features & ANDROID_CPU_ARM_FEATURE_ARMv7) {
|
||||||
abi = "armeabi-v7a";
|
abi = "armeabi-v7a";
|
||||||
} else {
|
// } else {
|
||||||
abi = "armeabi";
|
// abi = "armeabi";
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
return env->NewStringUTF(abi);
|
return env->NewStringUTF(abi);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.github.shadowsocks"
|
package="com.github.shadowsocks"
|
||||||
android:versionCode="68"
|
android:versionCode="72"
|
||||||
android:versionName="2.2.0">
|
android:versionName="2.2.4">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||||
@@ -15,10 +15,11 @@
|
|||||||
android:required="false"/>
|
android:required="false"/>
|
||||||
|
|
||||||
<uses-sdk
|
<uses-sdk
|
||||||
android:minSdkVersion="9"
|
android:minSdkVersion="16"
|
||||||
android:targetSdkVersion="19"/>
|
android:targetSdkVersion="19"/>
|
||||||
|
|
||||||
<application
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
android:name=".ShadowsocksApplication"
|
android:name=".ShadowsocksApplication"
|
||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="true"
|
||||||
android:icon="@drawable/ic_launcher"
|
android:icon="@drawable/ic_launcher"
|
||||||
@@ -75,14 +76,12 @@
|
|||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".ShadowsocksNatService"
|
android:name=".ShadowsocksNatService"
|
||||||
android:process=":proxy"
|
|
||||||
android:exported="false">
|
android:exported="false">
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".ShadowsocksVpnService"
|
android:name=".ShadowsocksVpnService"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:process=":vpn"
|
|
||||||
android:permission="android.permission.BIND_VPN_SERVICE"
|
android:permission="android.permission.BIND_VPN_SERVICE"
|
||||||
android:exported="false">
|
android:exported="false">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 194 B After Width: | Height: | Size: 193 B |
|
Before Width: | Height: | Size: 201 B After Width: | Height: | Size: 198 B |
|
Before Width: | Height: | Size: 135 B After Width: | Height: | Size: 129 B |
|
Before Width: | Height: | Size: 118 B After Width: | Height: | Size: 125 B |
|
After Width: | Height: | Size: 113 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 514 B After Width: | Height: | Size: 461 B |
|
Before Width: | Height: | Size: 107 B After Width: | Height: | Size: 107 B |
|
Before Width: | Height: | Size: 100 B After Width: | Height: | Size: 100 B |
|
Before Width: | Height: | Size: 156 B After Width: | Height: | Size: 156 B |
|
Before Width: | Height: | Size: 166 B After Width: | Height: | Size: 166 B |
|
Before Width: | Height: | Size: 105 B After Width: | Height: | Size: 105 B |
|
Before Width: | Height: | Size: 114 B After Width: | Height: | Size: 134 B |
|
After Width: | Height: | Size: 110 B |
|
Before Width: | Height: | Size: 817 B After Width: | Height: | Size: 822 B |
|
Before Width: | Height: | Size: 370 B After Width: | Height: | Size: 351 B |
|
Before Width: | Height: | Size: 104 B After Width: | Height: | Size: 104 B |
|
Before Width: | Height: | Size: 97 B After Width: | Height: | Size: 97 B |
|
Before Width: | Height: | Size: 253 B After Width: | Height: | Size: 251 B |
|
Before Width: | Height: | Size: 260 B After Width: | Height: | Size: 259 B |
|
Before Width: | Height: | Size: 123 B After Width: | Height: | Size: 123 B |
|
Before Width: | Height: | Size: 125 B After Width: | Height: | Size: 129 B |
|
After Width: | Height: | Size: 114 B |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 677 B After Width: | Height: | Size: 603 B |
|
Before Width: | Height: | Size: 111 B After Width: | Height: | Size: 111 B |
|
Before Width: | Height: | Size: 101 B After Width: | Height: | Size: 101 B |
|
After Width: | Height: | Size: 357 B |
|
After Width: | Height: | Size: 351 B |
|
After Width: | Height: | Size: 350 B |
|
After Width: | Height: | Size: 255 B |
|
After Width: | Height: | Size: 352 B |
|
After Width: | Height: | Size: 140 B |
|
After Width: | Height: | Size: 131 B |
|
After Width: | Height: | Size: 148 B |
|
After Width: | Height: | Size: 372 B |
|
After Width: | Height: | Size: 360 B |
|
After Width: | Height: | Size: 163 B |
|
After Width: | Height: | Size: 137 B |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 156 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 157 B |
|
After Width: | Height: | Size: 480 B |
|
After Width: | Height: | Size: 481 B |
|
After Width: | Height: | Size: 805 B |
|
After Width: | Height: | Size: 744 B |
|
After Width: | Height: | Size: 116 B |
|
After Width: | Height: | Size: 116 B |
|
After Width: | Height: | Size: 110 B |
|
After Width: | Height: | Size: 102 B |
|
After Width: | Height: | Size: 102 B |
|
After Width: | Height: | Size: 110 B |
@@ -1,22 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- File created by the Android Action Bar Style Generator
|
|
||||||
|
|
||||||
Copyright (C) 2011 The Android Open Source Project
|
|
||||||
Copyright (C) 2012 readyState Software Ltd
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
|
||||||
<solid android:color="@color/pressed_shadow" />
|
|
||||||
</shape>
|
|
||||||
@@ -20,6 +20,6 @@
|
|||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:exitFadeDuration="@android:integer/config_mediumAnimTime" >
|
android:exitFadeDuration="@android:integer/config_mediumAnimTime" >
|
||||||
<item android:state_pressed="false" android:state_focused="true" android:drawable="@drawable/list_focused_shadow" />
|
<item android:state_pressed="false" android:state_focused="true" android:drawable="@drawable/list_focused_shadow" />
|
||||||
<item android:state_pressed="true" android:drawable="@drawable/pressed_background_shadow" />
|
<item android:state_pressed="true" android:drawable="@drawable/list_pressed_shadow" />
|
||||||
<item android:drawable="@android:color/transparent" />
|
<item android:drawable="@android:color/transparent" />
|
||||||
</selector>
|
</selector>
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_centerVertical="true"/>
|
android:layout_centerVertical="true"/>
|
||||||
|
|
||||||
<org.jraf.android.backport.switchwidget.Switch
|
<Switch
|
||||||
android:id="@+id/bypassSwitch"
|
android:id="@+id/bypassSwitch"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|||||||
@@ -15,8 +15,9 @@
|
|||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_centerVertical="true"/>
|
android:layout_centerVertical="true"/>
|
||||||
|
|
||||||
<org.jraf.android.backport.switchwidget.Switch
|
<Switch
|
||||||
android:id="@+id/switchButton"
|
android:id="@+id/switchButton"
|
||||||
|
android:switchTextAppearance="@android:style/TextAppearance.Small.Inverse"
|
||||||
android:enabled="false"
|
android:enabled="false"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- File created by the Android Action Bar Style Generator
|
|
||||||
|
|
||||||
Copyright (C) 2011 The Android Open Source Project
|
|
||||||
Copyright (C) 2012 readyState Software Ltd
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<resources>
|
|
||||||
|
|
||||||
<style name="PopupTheme" parent="@android:style/Theme.Holo.Light.Dialog.NoActionBar">
|
|
||||||
<item name="android:windowIsFloating">false</item>
|
|
||||||
<item name="android:windowContentOverlay">@null</item>
|
|
||||||
<item name="android:windowSoftInputMode">stateAlwaysHidden</item>
|
|
||||||
<item name="android:windowActionModeOverlay">true</item>
|
|
||||||
<item name="android:windowIsTranslucent">true</item>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
<style name="Theme.Shadow" parent="@style/Theme.Sherlock.Light.DarkActionBar">
|
|
||||||
<item name="android:actionBarItemBackground">@drawable/selectable_background_shadow</item>
|
|
||||||
<item name="android:popupMenuStyle">@style/PopupMenu.Shadow</item>
|
|
||||||
<item name="android:dropDownListViewStyle">@style/DropDownListView.Shadow</item>
|
|
||||||
<item name="android:actionBarTabStyle">@style/ActionBarTabStyle.Shadow</item>
|
|
||||||
<item name="android:actionDropDownStyle">@style/DropDownNav.Shadow</item>
|
|
||||||
<item name="android:actionBarStyle">@style/ActionBar.Solid.Shadow</item>
|
|
||||||
<item name="android:actionModeBackground">@drawable/cab_background_top_shadow</item>
|
|
||||||
<item name="android:actionModeSplitBackground">@drawable/cab_background_bottom_shadow</item>
|
|
||||||
<item name="android:actionModeCloseButtonStyle">@style/ActionButton.CloseMode.Shadow</item>
|
|
||||||
|
|
||||||
<!-- Light.DarkActionBar specific -->
|
|
||||||
<item name="android:actionBarWidgetTheme">@style/Theme.Shadow.Widget</item>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style name="ActionBar.Solid.Shadow" parent="@style/Widget.Sherlock.Light.ActionBar.Solid.Inverse">
|
|
||||||
<item name="android:background">@drawable/ab_background_textured_shadow</item>
|
|
||||||
<item name="android:backgroundStacked">@drawable/ab_stacked_solid_shadow</item>
|
|
||||||
<item name="android:backgroundSplit">@drawable/ab_background_textured_shadow</item>
|
|
||||||
<item name="android:progressBarStyle">@style/ProgressBar.Shadow</item>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style name="ActionBar.Transparent.Shadow" parent="@style/Widget.Sherlock.ActionBar">
|
|
||||||
<item name="android:background">@drawable/ab_transparent_shadow</item>
|
|
||||||
<item name="android:progressBarStyle">@style/ProgressBar.Shadow</item>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<!-- this style is only referenced in a Light.DarkActionBar based theme -->
|
|
||||||
<style name="Theme.Shadow.Widget" parent="@style/Theme.Sherlock">
|
|
||||||
<item name="android:popupMenuStyle">@style/PopupMenu.Shadow</item>
|
|
||||||
<item name="android:dropDownListViewStyle">@style/DropDownListView.Shadow</item>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
</resources>
|
|
||||||
@@ -44,8 +44,7 @@
|
|||||||
<string name="forward_stop">后台服务已停止。</string>
|
<string name="forward_stop">后台服务已停止。</string>
|
||||||
<string name="service_failed">请检查你的网络状态后并重试。</string>
|
<string name="service_failed">请检查你的网络状态后并重试。</string>
|
||||||
<string name="stop">停止服务</string>
|
<string name="stop">停止服务</string>
|
||||||
<string name="vpn_status">推荐通过通知栏关闭 VPN 服务</string>
|
<string name="vpn_error">无法启动服务:\"%s\"。</string>
|
||||||
<string name="vpn_error">无法启动 VPN 服务:\"%s\"。看来和你的设备存在兼容性问题,请使用 Root 模式。</string>
|
|
||||||
<string name="ok_iknow">确定</string>
|
<string name="ok_iknow">确定</string>
|
||||||
<string name="port_alert">端口号应大于1024</string>
|
<string name="port_alert">端口号应大于1024</string>
|
||||||
<string name="port_empty">端口号不能为空</string>
|
<string name="port_empty">端口号不能为空</string>
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
|
||||||
<resources>
|
|
||||||
<!--Replace placeholder ID with your tracking ID-->
|
|
||||||
<string name="ga_trackingId">UA-37082941-1</string>
|
|
||||||
|
|
||||||
<!--Enable Activity tracking-->
|
|
||||||
<bool name="ga_autoActivityTracking">true</bool>
|
|
||||||
|
|
||||||
<!--Enable automatic exception tracking-->
|
|
||||||
<bool name="ga_reportUncaughtExceptions">true</bool>
|
|
||||||
|
|
||||||
<!-- Set a session timeout period of 1 week -->
|
|
||||||
<integer name="ga_sessionTimeout">604800</integer>
|
|
||||||
</resources>
|
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
<string-array name="enc_method_entry">
|
<string-array name="enc_method_entry">
|
||||||
<item>TABLE</item>
|
<item>TABLE</item>
|
||||||
<item>RC4</item>
|
<item>RC4</item>
|
||||||
|
<item>RC4-MD5</item>
|
||||||
<item>AES-128-CFB</item>
|
<item>AES-128-CFB</item>
|
||||||
<item>AES-192-CFB</item>
|
<item>AES-192-CFB</item>
|
||||||
<item>AES-256-CFB</item>
|
<item>AES-256-CFB</item>
|
||||||
@@ -22,6 +23,7 @@
|
|||||||
<string-array name="enc_method_value">
|
<string-array name="enc_method_value">
|
||||||
<item>table</item>
|
<item>table</item>
|
||||||
<item>rc4</item>
|
<item>rc4</item>
|
||||||
|
<item>rc4-md5</item>
|
||||||
<item>aes-128-cfb</item>
|
<item>aes-128-cfb</item>
|
||||||
<item>aes-192-cfb</item>
|
<item>aes-192-cfb</item>
|
||||||
<item>aes-256-cfb</item>
|
<item>aes-256-cfb</item>
|
||||||
|
|||||||
@@ -1,18 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
|
||||||
Zirco Browser for Android
|
|
||||||
|
|
||||||
Copyright (C) 2010 J. Devauchelle and contributors.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License
|
|
||||||
version 3 as published by the Free Software Foundation.
|
|
||||||
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
|
|||||||
@@ -57,8 +57,7 @@
|
|||||||
<string name="forward_stop">Shadowsocks stopped.</string>
|
<string name="forward_stop">Shadowsocks stopped.</string>
|
||||||
<string name="service_failed">Please check your network status and try again.</string>
|
<string name="service_failed">Please check your network status and try again.</string>
|
||||||
<string name="stop">Stop the service</string>
|
<string name="stop">Stop the service</string>
|
||||||
<string name="vpn_status">Recommend to disable the VPN service through the notification bar.</string>
|
<string name="vpn_error">Unable to start service: "%s".</string>
|
||||||
<string name="vpn_error">Unable to start VPN service: "%s". It seems to be a compatibility issue with your device. Please consider using ROOT mode instead.</string>
|
|
||||||
|
|
||||||
<!-- alert category -->
|
<!-- alert category -->
|
||||||
<string name="ok_iknow">OK</string>
|
<string name="ok_iknow">OK</string>
|
||||||
|
|||||||
@@ -16,54 +16,60 @@
|
|||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<style name="Widget.Shadow.Switch" parent="@style/Widget.Holo.CompoundButton.Switch">
|
<style name="Theme.AppManager" parent="@style/Theme.Shadow">
|
||||||
<item name="switchTextAppearance">@android:style/TextAppearance.Small.Inverse</item>
|
</style>
|
||||||
</style>
|
|
||||||
|
|
||||||
<!-- Variation on the Light theme that turns off the title -->
|
<style name="PopupTheme" parent="@android:style/Theme.Translucent.NoTitleBar">
|
||||||
<style name="Theme.Shadowsocks" parent="@style/Theme.Shadow">
|
<item name="android:windowFrame">@null</item>
|
||||||
<item name="switchStyle">@style/Widget.Shadow.Switch</item>
|
<item name="android:windowIsFloating">false</item>
|
||||||
<item name="menuDrawerStyle">@style/MenuDrawerStyle</item>
|
<item name="android:windowContentOverlay">@null</item>
|
||||||
</style>
|
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
|
||||||
|
<item name="android:windowSoftInputMode">stateAlwaysHidden</item>
|
||||||
|
<item name="android:windowActionModeOverlay">true</item>
|
||||||
|
<item name="android:colorBackgroundCacheHint">@null</item>
|
||||||
|
<item name="android:windowCloseOnTouchOutside">true</item>
|
||||||
|
<item name="android:windowIsTranslucent">true</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
<style name="Theme.AppManager" parent="@style/Theme.Shadow">
|
<!-- Variation on the Light theme that turns off the title -->
|
||||||
<item name="switchStyle">@style/Widget.Holo.Light.CompoundButton.Switch</item>
|
<style name="Theme.Shadowsocks" parent="@style/Theme.Shadow">
|
||||||
</style>
|
<item name="menuDrawerStyle">@style/MenuDrawerStyle</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
<style name="MenuDrawer"/>
|
<style name="MenuDrawer"/>
|
||||||
|
|
||||||
<style name="MenuDrawer.Widget"/>
|
<style name="MenuDrawer.Widget"/>
|
||||||
|
|
||||||
<style name="MenuDrawer.Widget.Category">
|
<style name="MenuDrawer.Widget.Category">
|
||||||
<item name="android:textStyle">bold</item>
|
<item name="android:textStyle">bold</item>
|
||||||
<item name="android:textColor">?android:attr/textColorSecondaryInverse</item>
|
<item name="android:textColor">?android:attr/textColorSecondaryInverse</item>
|
||||||
<item name="android:textSize">14sp</item>
|
<item name="android:textSize">14sp</item>
|
||||||
<item name="android:textAllCaps">true</item>
|
<item name="android:textAllCaps">true</item>
|
||||||
|
|
||||||
<item name="android:gravity">center_vertical</item>
|
<item name="android:gravity">center_vertical</item>
|
||||||
<item name="android:paddingLeft">16dp</item>
|
<item name="android:paddingLeft">16dp</item>
|
||||||
<item name="android:background">@drawable/md__category_background</item>
|
<item name="android:background">@drawable/md__category_background</item>
|
||||||
|
|
||||||
<item name="android:singleLine">true</item>
|
<item name="android:singleLine">true</item>
|
||||||
<item name="android:ellipsize">end</item>
|
<item name="android:ellipsize">end</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="MenuDrawer.Widget.Title">
|
<style name="MenuDrawer.Widget.Title">
|
||||||
<item name="android:background">@drawable/md__list_selector_holo_dark</item>
|
<item name="android:background">@drawable/md__list_selector_holo_dark</item>
|
||||||
<item name="android:textAppearance">?android:attr/textAppearance</item>
|
<item name="android:textAppearance">?android:attr/textAppearance</item>
|
||||||
<item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
|
<item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
|
||||||
<item name="android:textSize">18sp</item>
|
<item name="android:textSize">18sp</item>
|
||||||
<item name="android:paddingLeft">16dp</item>
|
<item name="android:paddingLeft">16dp</item>
|
||||||
<item name="android:paddingRight">32dp</item>
|
<item name="android:paddingRight">32dp</item>
|
||||||
<item name="android:paddingTop">8dp</item>
|
<item name="android:paddingTop">8dp</item>
|
||||||
<item name="android:paddingBottom">8dp</item>
|
<item name="android:paddingBottom">8dp</item>
|
||||||
<item name="android:drawablePadding">16dp</item>
|
<item name="android:drawablePadding">16dp</item>
|
||||||
<item name="android:gravity">center_vertical</item>
|
<item name="android:gravity">center_vertical</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="MenuDrawerStyle" parent="Widget.MenuDrawer">
|
<style name="MenuDrawerStyle" parent="Widget.MenuDrawer">
|
||||||
<item name="mdActiveIndicator">@drawable/menu_arrow</item>
|
<item name="mdActiveIndicator">@drawable/menu_arrow</item>
|
||||||
<item name="mdMenuSize">250dp</item>
|
<item name="mdMenuSize">250dp</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -19,77 +19,64 @@
|
|||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<style name="PopupTheme" parent="@android:style/Theme.Translucent.NoTitleBar">
|
<style name="Theme.Shadow" parent="@android:style/Theme.Holo.Light.DarkActionBar">
|
||||||
<item name="android:windowFrame">@null</item>
|
<item name="android:actionBarItemBackground">@drawable/selectable_background_shadow</item>
|
||||||
<item name="android:windowIsFloating">false</item>
|
<item name="android:popupMenuStyle">@style/PopupMenu.Shadow</item>
|
||||||
<item name="android:windowContentOverlay">@null</item>
|
<item name="android:dropDownListViewStyle">@style/DropDownListView.Shadow</item>
|
||||||
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
|
<item name="android:actionBarTabStyle">@style/ActionBarTabStyle.Shadow</item>
|
||||||
<item name="android:windowSoftInputMode">stateAlwaysHidden</item>
|
<item name="android:actionDropDownStyle">@style/DropDownNav.Shadow</item>
|
||||||
<item name="android:windowActionModeOverlay">true</item>
|
<item name="android:actionBarStyle">@style/ActionBar.Solid.Shadow</item>
|
||||||
<item name="android:colorBackgroundCacheHint">@null</item>
|
<item name="android:actionModeBackground">@drawable/cab_background_top_shadow</item>
|
||||||
<item name="android:windowCloseOnTouchOutside">true</item>
|
<item name="android:actionModeSplitBackground">@drawable/cab_background_bottom_shadow</item>
|
||||||
<item name="android:windowIsTranslucent">true</item>
|
<item name="android:actionModeCloseButtonStyle">@style/ActionButton.CloseMode.Shadow</item>
|
||||||
<item name="windowContentOverlay">@null</item>
|
|
||||||
</style>
|
<!-- Light.DarkActionBar specific -->
|
||||||
|
<item name="android:actionBarWidgetTheme">@style/Theme.Shadow.Widget</item>
|
||||||
<style name="Theme.Shadow" parent="@style/Theme.Sherlock.Light.DarkActionBar">
|
|
||||||
<item name="actionBarItemBackground">@drawable/selectable_background_shadow</item>
|
|
||||||
<item name="popupMenuStyle">@style/PopupMenu.Shadow</item>
|
|
||||||
<item name="dropDownListViewStyle">@style/DropDownListView.Shadow</item>
|
|
||||||
<item name="actionBarTabStyle">@style/ActionBarTabStyle.Shadow</item>
|
|
||||||
<item name="actionDropDownStyle">@style/DropDownNav.Shadow</item>
|
|
||||||
<item name="actionBarStyle">@style/ActionBar.Solid.Shadow</item>
|
|
||||||
<item name="actionModeBackground">@drawable/cab_background_top_shadow</item>
|
|
||||||
<item name="actionModeSplitBackground">@drawable/cab_background_bottom_shadow</item>
|
|
||||||
<item name="actionModeCloseButtonStyle">@style/ActionButton.CloseMode.Shadow</item>
|
|
||||||
|
|
||||||
<!-- Light.DarkActionBar specific -->
|
|
||||||
<item name="actionBarWidgetTheme">@style/Theme.Shadow.Widget</item>
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="ActionBar.Solid.Shadow" parent="@style/Widget.Sherlock.Light.ActionBar.Solid.Inverse">
|
<style name="ActionBar.Solid.Shadow" parent="@android:style/Widget.Holo.Light.ActionBar.Solid.Inverse">
|
||||||
<item name="background">@drawable/ab_solid_shadow</item>
|
<item name="android:background">@drawable/ab_background_textured_shadow</item>
|
||||||
<item name="backgroundStacked">@drawable/ab_stacked_solid_shadow</item>
|
<item name="android:backgroundStacked">@drawable/ab_stacked_solid_shadow</item>
|
||||||
<item name="backgroundSplit">@drawable/ab_bottom_solid_shadow</item>
|
<item name="android:backgroundSplit">@drawable/ab_background_textured_shadow</item>
|
||||||
<item name="progressBarStyle">@style/ProgressBar.Shadow</item>
|
<item name="android:progressBarStyle">@style/ProgressBar.Shadow</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="ActionBar.Transparent.Shadow" parent="@style/Widget.Sherlock.ActionBar">
|
<style name="ActionBar.Transparent.Shadow" parent="@android:style/Widget.Holo.ActionBar">
|
||||||
<item name="background">@drawable/ab_transparent_shadow</item>
|
<item name="android:background">@drawable/ab_transparent_shadow</item>
|
||||||
<item name="progressBarStyle">@style/ProgressBar.Shadow</item>
|
<item name="android:progressBarStyle">@style/ProgressBar.Shadow</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="PopupMenu.Shadow" parent="@style/Widget.Sherlock.ListPopupWindow">
|
<style name="PopupMenu.Shadow" parent="@android:style/Widget.Holo.ListPopupWindow">
|
||||||
<item name="android:popupBackground">@drawable/menu_dropdown_panel_shadow</item>
|
<item name="android:popupBackground">@drawable/menu_dropdown_panel_shadow</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="DropDownListView.Shadow" parent="@style/Widget.Sherlock.ListView.DropDown">
|
<style name="DropDownListView.Shadow" parent="@android:style/Widget.Holo.ListView.DropDown">
|
||||||
<item name="android:listSelector">@drawable/selectable_background_shadow</item>
|
<item name="android:listSelector">@drawable/selectable_background_shadow</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="ActionBarTabStyle.Shadow" parent="@style/Widget.Sherlock.ActionBar.TabView">
|
<style name="ActionBarTabStyle.Shadow" parent="@android:style/Widget.Holo.ActionBar.TabView">
|
||||||
<item name="android:background">@drawable/tab_indicator_ab_shadow</item>
|
<item name="android:background">@drawable/tab_indicator_ab_shadow</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="DropDownNav.Shadow" parent="@style/Widget.Sherlock.Spinner.DropDown.ActionBar">
|
<style name="DropDownNav.Shadow" parent="@android:style/Widget.Holo.Spinner">
|
||||||
<item name="android:background">@drawable/spinner_background_ab_shadow</item>
|
<item name="android:background">@drawable/spinner_background_ab_shadow</item>
|
||||||
<item name="android:popupBackground">@drawable/menu_dropdown_panel_shadow</item>
|
<item name="android:popupBackground">@drawable/menu_dropdown_panel_shadow</item>
|
||||||
<item name="android:dropDownSelector">@drawable/selectable_background_shadow</item>
|
<item name="android:dropDownSelector">@drawable/selectable_background_shadow</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="ProgressBar.Shadow" parent="@style/Widget.Sherlock.ProgressBar.Horizontal">
|
<style name="ProgressBar.Shadow" parent="@android:style/Widget.Holo.ProgressBar.Horizontal">
|
||||||
<item name="android:progressDrawable">@drawable/progress_horizontal_shadow</item>
|
<item name="android:progressDrawable">@drawable/progress_horizontal_shadow</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="ActionButton.CloseMode.Shadow" parent="@style/Widget.Sherlock.ActionButton.CloseMode">
|
<style name="ActionButton.CloseMode.Shadow" parent="@android:style/Widget.Holo.ActionButton.CloseMode">
|
||||||
<item name="android:background">@drawable/btn_cab_done_shadow</item>
|
<item name="android:background">@drawable/btn_cab_done_shadow</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!-- this style is only referenced in a Light.DarkActionBar based theme -->
|
<!-- this style is only referenced in a Light.DarkActionBar based theme -->
|
||||||
<style name="Theme.Shadow.Widget" parent="@style/Theme.Sherlock">
|
<style name="Theme.Shadow.Widget" parent="@android:style/Theme.Holo">
|
||||||
<item name="popupMenuStyle">@style/PopupMenu.Shadow</item>
|
<item name="android:popupMenuStyle">@style/PopupMenu.Shadow</item>
|
||||||
<item name="dropDownListViewStyle">@style/DropDownListView.Shadow</item>
|
<item name="android:dropDownListViewStyle">@style/DropDownListView.Shadow</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<!-- Set a session timeout period of 1 week -->
|
||||||
|
<integer name="ga_sessionTimeout">604800</integer>
|
||||||
|
|
||||||
|
<!-- Enable automatic Activity measurement -->
|
||||||
|
<bool name="ga_autoActivityTracking">true</bool>
|
||||||
|
|
||||||
|
<!-- The screen names that will appear in reports -->
|
||||||
|
<screenName name="com.google.android.gms.analytics.samples.mobileplayground.ScreenviewFragment">
|
||||||
|
Shadowsocks ScreenView
|
||||||
|
</screenName>
|
||||||
|
<screenName name="com.google.android.gms.analytics.samples.mobileplayground.EcommerceFragment">
|
||||||
|
Shadowsocks EcommerceView
|
||||||
|
</screenName>
|
||||||
|
<!-- The following value should be replaced with correct property id. -->
|
||||||
|
<string name="ga_trackingId">UA-37082941-1</string>
|
||||||
|
</resources>
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
package com.github.shadowsocks
|
package com.github.shadowsocks
|
||||||
|
|
||||||
import android.app.ProgressDialog
|
import android.app.{Activity, ProgressDialog}
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
@@ -53,23 +53,13 @@ import android.view.View.OnClickListener
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.ViewGroup.LayoutParams
|
import android.view.ViewGroup.LayoutParams
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.widget.AbsListView
|
import android.widget._
|
||||||
import android.widget.AbsListView.OnScrollListener
|
import android.widget.AbsListView.OnScrollListener
|
||||||
import android.widget.ArrayAdapter
|
|
||||||
import android.widget.CheckBox
|
|
||||||
import android.widget.CompoundButton
|
|
||||||
import android.widget.CompoundButton.OnCheckedChangeListener
|
import android.widget.CompoundButton.OnCheckedChangeListener
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.ListAdapter
|
|
||||||
import android.widget.ListView
|
|
||||||
import android.widget.TextView
|
|
||||||
import com.actionbarsherlock.app.SherlockActivity
|
|
||||||
import com.nostra13.universalimageloader.core.download.BaseImageDownloader
|
import com.nostra13.universalimageloader.core.download.BaseImageDownloader
|
||||||
import java.io.{ByteArrayOutputStream, ByteArrayInputStream, InputStream}
|
import java.io.{ByteArrayOutputStream, ByteArrayInputStream, InputStream}
|
||||||
import com.nostra13.universalimageloader.core.{DisplayImageOptions, ImageLoader, ImageLoaderConfiguration}
|
import com.nostra13.universalimageloader.core.{DisplayImageOptions, ImageLoader, ImageLoaderConfiguration}
|
||||||
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer
|
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer
|
||||||
import com.google.analytics.tracking.android.EasyTracker
|
|
||||||
import org.jraf.android.backport.switchwidget.Switch
|
|
||||||
import com.github.shadowsocks.utils.{Utils, Scheme, Key}
|
import com.github.shadowsocks.utils.{Utils, Scheme, Key}
|
||||||
|
|
||||||
case class ProxiedApp(uid: Int, name: String, var proxied: Boolean)
|
case class ProxiedApp(uid: Int, name: String, var proxied: Boolean)
|
||||||
@@ -106,7 +96,7 @@ object AppManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AppManager extends SherlockActivity with OnCheckedChangeListener with OnClickListener {
|
class AppManager extends Activity with OnCheckedChangeListener with OnClickListener {
|
||||||
|
|
||||||
val MSG_LOAD_START = 1
|
val MSG_LOAD_START = 1
|
||||||
val MSG_LOAD_FINISH = 2
|
val MSG_LOAD_FINISH = 2
|
||||||
@@ -216,9 +206,20 @@ class AppManager extends SherlockActivity with OnCheckedChangeListener with OnCl
|
|||||||
saveAppSettings(this)
|
saveAppSettings(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override def onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
if (handler != null) {
|
||||||
|
handler.removeCallbacksAndMessages(null)
|
||||||
|
handler = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected override def onCreate(savedInstanceState: Bundle) {
|
protected override def onCreate(savedInstanceState: Bundle) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
getSupportActionBar.setTitle(R.string.proxied_help)
|
|
||||||
|
handler = new Handler()
|
||||||
|
|
||||||
|
getActionBar.setTitle(R.string.proxied_help)
|
||||||
this.setContentView(R.layout.layout_apps)
|
this.setContentView(R.layout.layout_apps)
|
||||||
this.overlay = View.inflate(this, R.layout.overlay, null).asInstanceOf[TextView]
|
this.overlay = View.inflate(this, R.layout.overlay, null).asInstanceOf[TextView]
|
||||||
getWindowManager.addView(overlay, new
|
getWindowManager.addView(overlay, new
|
||||||
@@ -233,7 +234,7 @@ class AppManager extends SherlockActivity with OnCheckedChangeListener with OnCl
|
|||||||
.build()
|
.build()
|
||||||
ImageLoader.getInstance().init(config)
|
ImageLoader.getInstance().init(config)
|
||||||
|
|
||||||
val bypassSwitch: Switch = findViewById(R.id.bypassSwitch).asInstanceOf[Switch]
|
val bypassSwitch = findViewById(R.id.bypassSwitch).asInstanceOf[Switch]
|
||||||
val prefs: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(getBaseContext)
|
val prefs: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(getBaseContext)
|
||||||
bypassSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener {
|
bypassSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener {
|
||||||
def onCheckedChanged(button: CompoundButton, checked: Boolean) {
|
def onCheckedChanged(button: CompoundButton, checked: Boolean) {
|
||||||
@@ -247,24 +248,14 @@ class AppManager extends SherlockActivity with OnCheckedChangeListener with OnCl
|
|||||||
super.onResume()
|
super.onResume()
|
||||||
new Thread {
|
new Thread {
|
||||||
override def run() {
|
override def run() {
|
||||||
handler.sendEmptyMessage(MSG_LOAD_START)
|
handler.post(loadStartRunnable)
|
||||||
appListView = findViewById(R.id.applistview).asInstanceOf[ListView]
|
appListView = findViewById(R.id.applistview).asInstanceOf[ListView]
|
||||||
if (!appsLoaded) loadApps()
|
if (!appsLoaded) loadApps()
|
||||||
handler.sendEmptyMessage(MSG_LOAD_FINISH)
|
handler.post(loadFinishRunnable)
|
||||||
}
|
}
|
||||||
}.start()
|
}.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override def onStart() {
|
|
||||||
super.onStart()
|
|
||||||
EasyTracker.getInstance(this).activityStart(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override def onStop() {
|
|
||||||
super.onStop()
|
|
||||||
EasyTracker.getInstance(this).activityStop(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
def saveAppSettings(context: Context) {
|
def saveAppSettings(context: Context) {
|
||||||
if (apps == null) return
|
if (apps == null) return
|
||||||
val prefs: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
|
val prefs: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
@@ -279,46 +270,46 @@ class AppManager extends SherlockActivity with OnCheckedChangeListener with OnCl
|
|||||||
edit.commit
|
edit.commit
|
||||||
}
|
}
|
||||||
|
|
||||||
val handler: Handler = new Handler {
|
val loadStartRunnable = new Runnable {
|
||||||
override def handleMessage(msg: Message) {
|
override def run() {
|
||||||
msg.what match {
|
progressDialog = ProgressDialog
|
||||||
case MSG_LOAD_START =>
|
.show(AppManager.this, "", getString(R.string.loading), true, true)
|
||||||
progressDialog = ProgressDialog
|
|
||||||
.show(AppManager.this, "", getString(R.string.loading), true, true)
|
|
||||||
case MSG_LOAD_FINISH =>
|
|
||||||
appListView.setAdapter(adapter)
|
|
||||||
appListView.setOnScrollListener(new AbsListView.OnScrollListener {
|
|
||||||
def onScroll(view: AbsListView, firstVisibleItem: Int, visibleItemCount: Int,
|
|
||||||
totalItemCount: Int) {
|
|
||||||
if (visible) {
|
|
||||||
val name: String = apps(firstVisibleItem).name
|
|
||||||
if (name != null && name.length > 1) {
|
|
||||||
overlay.setText(apps(firstVisibleItem).name.substring(0, 1))
|
|
||||||
} else {
|
|
||||||
overlay.setText("*")
|
|
||||||
}
|
|
||||||
overlay.setVisibility(View.VISIBLE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def onScrollStateChanged(view: AbsListView, scrollState: Int) {
|
|
||||||
visible = true
|
|
||||||
if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) {
|
|
||||||
overlay.setVisibility(View.INVISIBLE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var visible = false
|
|
||||||
})
|
|
||||||
if (progressDialog != null) {
|
|
||||||
progressDialog.dismiss()
|
|
||||||
progressDialog = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
super.handleMessage(msg)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val loadFinishRunnable = new Runnable {
|
||||||
|
override def run() = {
|
||||||
|
appListView.setAdapter(adapter)
|
||||||
|
appListView.setOnScrollListener(new AbsListView.OnScrollListener {
|
||||||
|
def onScroll(view: AbsListView, firstVisibleItem: Int, visibleItemCount: Int,
|
||||||
|
totalItemCount: Int) {
|
||||||
|
if (visible) {
|
||||||
|
val name: String = apps(firstVisibleItem).name
|
||||||
|
if (name != null && name.length > 1) {
|
||||||
|
overlay.setText(apps(firstVisibleItem).name.substring(0, 1))
|
||||||
|
} else {
|
||||||
|
overlay.setText("*")
|
||||||
|
}
|
||||||
|
overlay.setVisibility(View.VISIBLE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
def onScrollStateChanged(view: AbsListView, scrollState: Int) {
|
||||||
|
visible = true
|
||||||
|
if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) {
|
||||||
|
overlay.setVisibility(View.INVISIBLE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var visible = false
|
||||||
|
})
|
||||||
|
if (progressDialog != null) {
|
||||||
|
progressDialog.dismiss()
|
||||||
|
progressDialog = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var handler: Handler = null
|
||||||
|
|
||||||
class AppIconDownloader(context: Context, connectTimeout: Int, readTimeout: Int)
|
class AppIconDownloader(context: Context, connectTimeout: Int, readTimeout: Int)
|
||||||
extends BaseImageDownloader(context, connectTimeout, readTimeout) {
|
extends BaseImageDownloader(context, connectTimeout, readTimeout) {
|
||||||
|
|
||||||
|
|||||||
@@ -54,21 +54,20 @@ import android.util.{DisplayMetrics, Log}
|
|||||||
import android.view._
|
import android.view._
|
||||||
import android.webkit.{WebView, WebViewClient}
|
import android.webkit.{WebView, WebViewClient}
|
||||||
import android.widget._
|
import android.widget._
|
||||||
import com.actionbarsherlock.app.SherlockPreferenceActivity
|
|
||||||
import com.github.shadowsocks.aidl.{IShadowsocksService, IShadowsocksServiceCallback}
|
import com.github.shadowsocks.aidl.{IShadowsocksService, IShadowsocksServiceCallback}
|
||||||
import com.github.shadowsocks.database._
|
import com.github.shadowsocks.database._
|
||||||
import com.github.shadowsocks.preferences.{PasswordEditTextPreference, ProfileEditTextPreference, SummaryEditTextPreference}
|
import com.github.shadowsocks.preferences.{PasswordEditTextPreference, ProfileEditTextPreference, SummaryEditTextPreference}
|
||||||
import com.github.shadowsocks.utils._
|
import com.github.shadowsocks.utils._
|
||||||
import com.google.analytics.tracking.android.{EasyTracker, MapBuilder}
|
|
||||||
import com.google.android.gms.ads.{AdRequest, AdSize, AdView}
|
import com.google.android.gms.ads.{AdRequest, AdSize, AdView}
|
||||||
|
import com.google.android.gms.analytics.HitBuilders
|
||||||
import com.google.zxing.integration.android.IntentIntegrator
|
import com.google.zxing.integration.android.IntentIntegrator
|
||||||
import com.nostra13.universalimageloader.core.download.BaseImageDownloader
|
import com.nostra13.universalimageloader.core.download.BaseImageDownloader
|
||||||
import de.keyboardsurfer.android.widget.crouton.{Configuration, Crouton, Style}
|
import de.keyboardsurfer.android.widget.crouton.{Configuration, Crouton, Style}
|
||||||
import net.simonvt.menudrawer.MenuDrawer
|
import net.simonvt.menudrawer.MenuDrawer
|
||||||
import org.jraf.android.backport.switchwidget.Switch
|
|
||||||
|
|
||||||
import scala.collection.mutable.{ArrayBuffer, ListBuffer}
|
import scala.collection.mutable.{ArrayBuffer, ListBuffer}
|
||||||
import scala.concurrent.ops._
|
import scala.concurrent.ops._
|
||||||
|
import scala.ref.WeakReference
|
||||||
|
|
||||||
class ProfileIconDownloader(context: Context, connectTimeout: Int, readTimeout: Int)
|
class ProfileIconDownloader(context: Context, connectTimeout: Int, readTimeout: Int)
|
||||||
extends BaseImageDownloader(context, connectTimeout, readTimeout) {
|
extends BaseImageDownloader(context, connectTimeout, readTimeout) {
|
||||||
@@ -169,7 +168,7 @@ object Shadowsocks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Shadowsocks
|
class Shadowsocks
|
||||||
extends SherlockPreferenceActivity
|
extends PreferenceActivity
|
||||||
with CompoundButton.OnCheckedChangeListener
|
with CompoundButton.OnCheckedChangeListener
|
||||||
with MenuAdapter.MenuListener {
|
with MenuAdapter.MenuListener {
|
||||||
|
|
||||||
@@ -214,6 +213,8 @@ class Shadowsocks
|
|||||||
setPreferenceEnabled(enabled = false)
|
setPreferenceEnabled(enabled = false)
|
||||||
}
|
}
|
||||||
state = bgService.getState
|
state = bgService.getState
|
||||||
|
// set the listener
|
||||||
|
switchButton.setOnCheckedChangeListener(Shadowsocks.this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override def onServiceDisconnected(name: ComponentName) {
|
override def onServiceDisconnected(name: ComponentName) {
|
||||||
@@ -227,16 +228,18 @@ class Shadowsocks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy val settings = PreferenceManager.getDefaultSharedPreferences(this)
|
private lazy val settings = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
lazy val status = getSharedPreferences(Key.status, Context.MODE_PRIVATE)
|
private lazy val status = getSharedPreferences(Key.status, Context.MODE_PRIVATE)
|
||||||
lazy val preferenceReceiver = new PreferenceBroadcastReceiver
|
private lazy val preferenceReceiver = new PreferenceBroadcastReceiver
|
||||||
lazy val drawer = MenuDrawer.attach(this)
|
private lazy val drawer = MenuDrawer.attach(this)
|
||||||
lazy val menuAdapter = new MenuAdapter(this, getMenuList)
|
private lazy val menuAdapter = new MenuAdapter(this, getMenuList)
|
||||||
lazy val listView = new ListView(this)
|
private lazy val listView = new ListView(this)
|
||||||
lazy val profileManager =
|
private lazy val profileManager =
|
||||||
new ProfileManager(settings, getApplication.asInstanceOf[ShadowsocksApplication].dbHelper)
|
new ProfileManager(settings, getApplication.asInstanceOf[ShadowsocksApplication].dbHelper)
|
||||||
|
|
||||||
val handler = new Handler()
|
private lazy val application = getApplication.asInstanceOf[ShadowsocksApplication]
|
||||||
|
|
||||||
|
var handler: Handler = null
|
||||||
|
|
||||||
def isSinglePane: Boolean = {
|
def isSinglePane: Boolean = {
|
||||||
if (singlePane == -1) {
|
if (singlePane == -1) {
|
||||||
@@ -442,6 +445,8 @@ class Shadowsocks
|
|||||||
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
handler = new Handler()
|
||||||
|
|
||||||
addPreferencesFromResource(R.xml.pref_all)
|
addPreferencesFromResource(R.xml.pref_all)
|
||||||
|
|
||||||
// Initialize the profile
|
// Initialize the profile
|
||||||
@@ -481,10 +486,10 @@ class Shadowsocks
|
|||||||
val tf: Typeface = Typefaces.get(this, "fonts/Iceland.ttf")
|
val tf: Typeface = Typefaces.get(this, "fonts/Iceland.ttf")
|
||||||
if (tf != null) title.setTypeface(tf)
|
if (tf != null) title.setTypeface(tf)
|
||||||
switchButton = switchLayout.findViewById(R.id.switchButton).asInstanceOf[Switch]
|
switchButton = switchLayout.findViewById(R.id.switchButton).asInstanceOf[Switch]
|
||||||
getSupportActionBar.setCustomView(switchLayout)
|
getActionBar.setCustomView(switchLayout)
|
||||||
getSupportActionBar.setDisplayShowTitleEnabled(false)
|
getActionBar.setDisplayShowTitleEnabled(false)
|
||||||
getSupportActionBar.setDisplayShowCustomEnabled(true)
|
getActionBar.setDisplayShowCustomEnabled(true)
|
||||||
getSupportActionBar.setIcon(R.drawable.ic_stat_shadowsocks)
|
getActionBar.setIcon(R.drawable.ic_stat_shadowsocks)
|
||||||
|
|
||||||
// Register broadcast receiver
|
// Register broadcast receiver
|
||||||
registerReceiver(preferenceReceiver, new IntentFilter(Action.UPDATE_PREFS))
|
registerReceiver(preferenceReceiver, new IntentFilter(Action.UPDATE_PREFS))
|
||||||
@@ -519,8 +524,8 @@ class Shadowsocks
|
|||||||
case ignored: RemoteException => // Nothing
|
case ignored: RemoteException => // Nothing
|
||||||
}
|
}
|
||||||
bgService = null
|
bgService = null
|
||||||
|
unbindService(connection)
|
||||||
}
|
}
|
||||||
unbindService(connection)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override def onRestoreInstanceState(inState: Bundle) {
|
override def onRestoreInstanceState(inState: Bundle) {
|
||||||
@@ -683,32 +688,40 @@ class Shadowsocks
|
|||||||
buf += new Category(getString(R.string.settings))
|
buf += new Category(getString(R.string.settings))
|
||||||
|
|
||||||
buf += new Item(-100, getString(R.string.recovery), android.R.drawable.ic_menu_revert, _ => {
|
buf += new Item(-100, getString(R.string.recovery), android.R.drawable.ic_menu_revert, _ => {
|
||||||
EasyTracker
|
// send event
|
||||||
.getInstance(this)
|
application.tracker.send(new HitBuilders.EventBuilder()
|
||||||
.send(MapBuilder.createEvent(Shadowsocks.TAG, "reset", getVersionName, null).build())
|
.setCategory(Shadowsocks.TAG)
|
||||||
|
.setAction("reset")
|
||||||
|
.setLabel(getVersionName)
|
||||||
|
.build())
|
||||||
recovery()
|
recovery()
|
||||||
})
|
})
|
||||||
|
|
||||||
buf +=
|
buf +=
|
||||||
new Item(-200, getString(R.string.flush_dnscache), android.R.drawable.ic_menu_delete, _ => {
|
new Item(-200, getString(R.string.flush_dnscache), android.R.drawable.ic_menu_delete, _ => {
|
||||||
EasyTracker
|
// send event
|
||||||
.getInstance(this)
|
application.tracker.send(new HitBuilders.EventBuilder()
|
||||||
.send(
|
.setCategory(Shadowsocks.TAG)
|
||||||
MapBuilder.createEvent(Shadowsocks.TAG, "flush_dnscache", getVersionName, null).build())
|
.setAction("flush_dnscache")
|
||||||
|
.setLabel(getVersionName)
|
||||||
|
.build())
|
||||||
flushDnsCache()
|
flushDnsCache()
|
||||||
})
|
})
|
||||||
|
|
||||||
buf += new Item(-300, getString(R.string.about), android.R.drawable.ic_menu_info_details, _ => {
|
buf += new Item(-300, getString(R.string.about), android.R.drawable.ic_menu_info_details, _ => {
|
||||||
EasyTracker
|
// send event
|
||||||
.getInstance(this)
|
application.tracker.send(new HitBuilders.EventBuilder()
|
||||||
.send(MapBuilder.createEvent(Shadowsocks.TAG, "about", getVersionName, null).build())
|
.setCategory(Shadowsocks.TAG)
|
||||||
|
.setAction("about")
|
||||||
|
.setLabel(getVersionName)
|
||||||
|
.build())
|
||||||
showAbout()
|
showAbout()
|
||||||
})
|
})
|
||||||
|
|
||||||
buf.toList
|
buf.toList
|
||||||
}
|
}
|
||||||
|
|
||||||
override def onOptionsItemSelected(item: com.actionbarsherlock.view.MenuItem): Boolean = {
|
override def onOptionsItemSelected(item: MenuItem): Boolean = {
|
||||||
item.getItemId match {
|
item.getItemId match {
|
||||||
case android.R.id.home =>
|
case android.R.id.home =>
|
||||||
drawer.toggleMenu()
|
drawer.toggleMenu()
|
||||||
@@ -735,9 +748,9 @@ class Shadowsocks
|
|||||||
changeSwitch(checked = false)
|
changeSwitch(checked = false)
|
||||||
}
|
}
|
||||||
state = bgService.getState
|
state = bgService.getState
|
||||||
|
// set the listener
|
||||||
|
switchButton.setOnCheckedChangeListener(Shadowsocks.this)
|
||||||
}
|
}
|
||||||
// set the listener
|
|
||||||
switchButton.setOnCheckedChangeListener(Shadowsocks.this)
|
|
||||||
ConfigUtils.refresh(this)
|
ConfigUtils.refresh(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -776,12 +789,10 @@ class Shadowsocks
|
|||||||
|
|
||||||
override def onStart() {
|
override def onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
EasyTracker.getInstance(this).activityStart(this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override def onStop() {
|
override def onStop() {
|
||||||
super.onStop()
|
super.onStop()
|
||||||
EasyTracker.getInstance(this).activityStop(this)
|
|
||||||
clearDialog()
|
clearDialog()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -791,6 +802,10 @@ class Shadowsocks
|
|||||||
Crouton.cancelAllCroutons()
|
Crouton.cancelAllCroutons()
|
||||||
unregisterReceiver(preferenceReceiver)
|
unregisterReceiver(preferenceReceiver)
|
||||||
new BackupManager(this).dataChanged()
|
new BackupManager(this).dataChanged()
|
||||||
|
if (handler != null) {
|
||||||
|
handler.removeCallbacksAndMessages(null)
|
||||||
|
handler = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def copyToSystem() {
|
def copyToSystem() {
|
||||||
@@ -810,11 +825,7 @@ class Shadowsocks
|
|||||||
|
|
||||||
crash_recovery()
|
crash_recovery()
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 16) {
|
copyAssets(System.getABI)
|
||||||
copyAssets("api-16/" + System.getABI)
|
|
||||||
} else {
|
|
||||||
copyAssets(System.getABI)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 20) {
|
if (Build.VERSION.SDK_INT >= 20) {
|
||||||
copyToSystem()
|
copyToSystem()
|
||||||
@@ -917,9 +928,6 @@ class Shadowsocks
|
|||||||
bgService.start(ConfigUtils.load(settings))
|
bgService.start(ConfigUtils.load(settings))
|
||||||
|
|
||||||
if (isVpnEnabled) {
|
if (isVpnEnabled) {
|
||||||
val style = new Style.Builder().setBackgroundColorValue(Style.holoBlueLight).build()
|
|
||||||
val config = new Configuration.Builder().setDuration(Configuration.DURATION_LONG).build()
|
|
||||||
Crouton.makeText(Shadowsocks.this, R.string.vpn_status, style).setConfiguration(config).show()
|
|
||||||
changeSwitch(checked = false)
|
changeSwitch(checked = false)
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
@@ -985,7 +993,6 @@ class Shadowsocks
|
|||||||
changeSwitch(checked = false)
|
changeSwitch(checked = false)
|
||||||
Crouton.cancelAllCroutons()
|
Crouton.cancelAllCroutons()
|
||||||
if (m != null) {
|
if (m != null) {
|
||||||
Crouton.cancelAllCroutons()
|
|
||||||
val style = new Style.Builder().setBackgroundColorValue(Style.holoRedLight).build()
|
val style = new Style.Builder().setBackgroundColorValue(Style.holoRedLight).build()
|
||||||
val config = new Configuration.Builder()
|
val config = new Configuration.Builder()
|
||||||
.setDuration(Configuration.DURATION_LONG)
|
.setDuration(Configuration.DURATION_LONG)
|
||||||
|
|||||||
@@ -39,26 +39,35 @@
|
|||||||
|
|
||||||
package com.github.shadowsocks
|
package com.github.shadowsocks
|
||||||
|
|
||||||
|
import java.util
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import com.github.shadowsocks.database.DBHelper
|
import com.github.shadowsocks.database.DBHelper
|
||||||
import com.google.tagmanager.{Container, ContainerOpener, TagManager}
|
|
||||||
import com.google.tagmanager.ContainerOpener.{Notifier, OpenType}
|
|
||||||
import com.google.tagmanager.Container.FunctionCallMacroHandler
|
|
||||||
import java.util
|
|
||||||
import com.github.shadowsocks.utils.Utils
|
import com.github.shadowsocks.utils.Utils
|
||||||
|
import com.google.android.gms.analytics.GoogleAnalytics
|
||||||
|
import com.google.android.gms.common.api.ResultCallback
|
||||||
|
import com.google.android.gms.tagmanager.Container.FunctionCallMacroCallback
|
||||||
|
import com.google.android.gms.tagmanager.{ContainerHolder, TagManager}
|
||||||
|
|
||||||
class ShadowsocksApplication extends Application {
|
class ShadowsocksApplication extends Application {
|
||||||
lazy val dbHelper = new DBHelper(this)
|
lazy val dbHelper = new DBHelper(this)
|
||||||
lazy val SIG_FUNC = "getSignature"
|
lazy val SIG_FUNC = "getSignature"
|
||||||
var tagContainer: Container = null
|
var containerHolder: ContainerHolder = null
|
||||||
|
lazy val tracker = GoogleAnalytics.getInstance(this).newTracker(R.xml.tracker)
|
||||||
|
|
||||||
override def onCreate() {
|
override def onCreate() {
|
||||||
val tm = TagManager.getInstance(this)
|
val tm = TagManager.getInstance(this)
|
||||||
ContainerOpener.openContainer(tm, "GTM-NT8WS8", OpenType.PREFER_NON_DEFAULT, null, new Notifier {
|
val pending = tm.loadContainerPreferNonDefault("GTM-NT8WS8", R.raw.gtm_default_container)
|
||||||
override def containerAvailable(container: Container) {
|
val callback = new ResultCallback[ContainerHolder] {
|
||||||
tagContainer = container
|
override def onResult(holder: ContainerHolder): Unit = {
|
||||||
container.registerFunctionCallMacroHandler(SIG_FUNC, new FunctionCallMacroHandler {
|
if (!holder.getStatus.isSuccess) {
|
||||||
def getValue(functionName: String, parameters: util.Map[String, AnyRef]): AnyRef = {
|
return
|
||||||
|
}
|
||||||
|
containerHolder = holder
|
||||||
|
val container = holder.getContainer
|
||||||
|
container.registerFunctionCallMacroCallback(SIG_FUNC, new FunctionCallMacroCallback {
|
||||||
|
override def getValue(functionName: String, parameters: util.Map[String, AnyRef]): AnyRef = {
|
||||||
if (functionName == SIG_FUNC) {
|
if (functionName == SIG_FUNC) {
|
||||||
Utils.getSignature(getApplicationContext)
|
Utils.getSignature(getApplicationContext)
|
||||||
}
|
}
|
||||||
@@ -66,6 +75,7 @@ class ShadowsocksApplication extends Application {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
pending.setResultCallback(callback, 2, TimeUnit.SECONDS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,8 +39,7 @@
|
|||||||
|
|
||||||
package com.github.shadowsocks
|
package com.github.shadowsocks
|
||||||
|
|
||||||
import android.app.backup.{FileBackupHelper, SharedPreferencesBackupHelper, BackupAgentHelper}
|
import android.app.backup.{BackupAgentHelper, FileBackupHelper, SharedPreferencesBackupHelper}
|
||||||
import android.content.Context
|
|
||||||
import com.github.shadowsocks.database.DBHelper
|
import com.github.shadowsocks.database.DBHelper
|
||||||
|
|
||||||
class ShadowsocksBackupAgent extends BackupAgentHelper {
|
class ShadowsocksBackupAgent extends BackupAgentHelper {
|
||||||
|
|||||||
@@ -39,30 +39,26 @@
|
|||||||
|
|
||||||
package com.github.shadowsocks
|
package com.github.shadowsocks
|
||||||
|
|
||||||
import android.app.Notification
|
import java.io.File
|
||||||
import android.app.NotificationManager
|
import java.lang.reflect.{InvocationTargetException, Method}
|
||||||
import android.app.PendingIntent
|
import java.util.{Timer, TimerTask}
|
||||||
import android.app.Service
|
|
||||||
|
import android.app.{Notification, NotificationManager, PendingIntent, Service}
|
||||||
import android.content._
|
import android.content._
|
||||||
import android.content.pm.PackageInfo
|
import android.content.pm.{PackageInfo, PackageManager}
|
||||||
import android.content.pm.PackageManager
|
import android.graphics.Color
|
||||||
|
import android.net.TrafficStats
|
||||||
import android.os._
|
import android.os._
|
||||||
import android.support.v4.app.NotificationCompat
|
import android.support.v4.app.NotificationCompat
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.google.analytics.tracking.android.{Fields, MapBuilder, EasyTracker}
|
|
||||||
import java.lang.reflect.InvocationTargetException
|
|
||||||
import java.lang.reflect.Method
|
|
||||||
import org.apache.http.conn.util.InetAddressUtils
|
|
||||||
import scala.collection._
|
|
||||||
import java.util.{TimerTask, Timer}
|
|
||||||
import android.net.TrafficStats
|
|
||||||
import scala.concurrent.ops._
|
|
||||||
import com.github.shadowsocks.utils._
|
|
||||||
import scala.Some
|
|
||||||
import android.graphics.Color
|
|
||||||
import com.github.shadowsocks.aidl.Config
|
import com.github.shadowsocks.aidl.Config
|
||||||
|
import com.github.shadowsocks.utils._
|
||||||
|
import com.google.android.gms.analytics.HitBuilders
|
||||||
|
import org.apache.http.conn.util.InetAddressUtils
|
||||||
|
|
||||||
|
import scala.collection._
|
||||||
import scala.collection.mutable.ArrayBuffer
|
import scala.collection.mutable.ArrayBuffer
|
||||||
import java.io.File
|
import scala.concurrent.ops._
|
||||||
|
|
||||||
case class TrafficStat(tx: Long, rx: Long, timestamp: Long)
|
case class TrafficStat(tx: Long, rx: Long, timestamp: Long)
|
||||||
|
|
||||||
@@ -100,7 +96,7 @@ class ShadowsocksNatService extends Service with BaseService {
|
|||||||
private var timer: Timer = null
|
private var timer: Timer = null
|
||||||
private val TIMER_INTERVAL = 2
|
private val TIMER_INTERVAL = 2
|
||||||
|
|
||||||
val handler: Handler = new Handler()
|
private lazy val application = getApplication.asInstanceOf[ShadowsocksApplication]
|
||||||
|
|
||||||
def isACLEnabled: Boolean = {
|
def isACLEnabled: Boolean = {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||||
@@ -220,12 +216,12 @@ class ShadowsocksNatService extends Service with BaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def notifyForegroundAlert(title: String, info: String, rate: Int) {
|
def notifyForegroundAlert(title: String, info: String, rate: Int) {
|
||||||
val openIntent: Intent = new Intent(this, classOf[Shadowsocks])
|
val openIntent = new Intent(this, classOf[Shadowsocks])
|
||||||
openIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
openIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
|
||||||
val contentIntent: PendingIntent = PendingIntent.getActivity(this, 0, openIntent, 0)
|
val contentIntent = PendingIntent.getActivity(this, 0, openIntent, 0)
|
||||||
val closeIntent: Intent = new Intent(Action.CLOSE)
|
val closeIntent = new Intent(Action.CLOSE)
|
||||||
val actionIntent: PendingIntent = PendingIntent.getBroadcast(this, 0, closeIntent, 0)
|
val actionIntent = PendingIntent.getBroadcast(this, 0, closeIntent, 0)
|
||||||
val builder: NotificationCompat.Builder = new NotificationCompat.Builder(this)
|
val builder = new NotificationCompat.Builder(this)
|
||||||
|
|
||||||
val icon = getResources.getDrawable(R.drawable.ic_stat_shadowsocks)
|
val icon = getResources.getDrawable(R.drawable.ic_stat_shadowsocks)
|
||||||
if (rate >= 0) {
|
if (rate >= 0) {
|
||||||
@@ -258,23 +254,8 @@ class ShadowsocksNatService extends Service with BaseService {
|
|||||||
startForegroundCompat(1, builder.build)
|
startForegroundCompat(1, builder.build)
|
||||||
}
|
}
|
||||||
|
|
||||||
def notifyAlert(title: String, info: String) {
|
|
||||||
val openIntent: Intent = new Intent(this, classOf[Shadowsocks])
|
|
||||||
openIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
|
||||||
val contentIntent: PendingIntent = PendingIntent.getActivity(this, 0, openIntent, 0)
|
|
||||||
val builder: NotificationCompat.Builder = new NotificationCompat.Builder(this)
|
|
||||||
builder
|
|
||||||
.setSmallIcon(R.drawable.ic_stat_shadowsocks)
|
|
||||||
.setWhen(0)
|
|
||||||
.setTicker(title)
|
|
||||||
.setContentTitle(getString(R.string.app_name))
|
|
||||||
.setContentText(info)
|
|
||||||
.setContentIntent(contentIntent)
|
|
||||||
.setAutoCancel(true)
|
|
||||||
notificationManager.notify(1, builder.build)
|
|
||||||
}
|
|
||||||
|
|
||||||
def onBind(intent: Intent): IBinder = {
|
def onBind(intent: Intent): IBinder = {
|
||||||
|
Log.d(TAG, "onBind")
|
||||||
if (Action.SERVICE == intent.getAction) {
|
if (Action.SERVICE == intent.getAction) {
|
||||||
binder
|
binder
|
||||||
} else {
|
} else {
|
||||||
@@ -309,14 +290,6 @@ class ShadowsocksNatService extends Service with BaseService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override def onStartCommand(intent: Intent, flags: Int, startId: Int): Int = {
|
|
||||||
Service.START_STICKY
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onTaskRemoved(intent: Intent) {
|
|
||||||
stopRunner()
|
|
||||||
}
|
|
||||||
|
|
||||||
def killProcesses() {
|
def killProcesses() {
|
||||||
Console.runRootCommand(Utils.getIptables + " -t nat -F OUTPUT")
|
Console.runRootCommand(Utils.getIptables + " -t nat -F OUTPUT")
|
||||||
|
|
||||||
@@ -462,12 +435,12 @@ class ShadowsocksNatService extends Service with BaseService {
|
|||||||
}
|
}
|
||||||
registerReceiver(receiver, filter)
|
registerReceiver(receiver, filter)
|
||||||
|
|
||||||
// start tracker
|
|
||||||
EasyTracker
|
// send event
|
||||||
.getInstance(this)
|
application.tracker.send(new HitBuilders.EventBuilder()
|
||||||
.send(MapBuilder
|
.setCategory(TAG)
|
||||||
.createEvent(TAG, "start", getVersionName, 0L)
|
.setAction("start")
|
||||||
.set(Fields.SESSION_CONTROL, "start")
|
.setLabel(getVersionName)
|
||||||
.build())
|
.build())
|
||||||
|
|
||||||
changeState(State.CONNECTING)
|
changeState(State.CONNECTING)
|
||||||
@@ -503,44 +476,46 @@ class ShadowsocksNatService extends Service with BaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
spawn {
|
spawn {
|
||||||
|
|
||||||
if (config.proxy == "198.199.101.152") {
|
if (config.proxy == "198.199.101.152") {
|
||||||
val container = getApplication.asInstanceOf[ShadowsocksApplication].tagContainer
|
val holder = application.containerHolder
|
||||||
try {
|
try {
|
||||||
config = ConfigUtils.getPublicConfig(getBaseContext, container, config)
|
config = ConfigUtils.getPublicConfig(getBaseContext, holder.getContainer, config)
|
||||||
} catch {
|
} catch {
|
||||||
case ex: Exception =>
|
case ex: Exception =>
|
||||||
notifyAlert(getString(R.string.forward_fail), getString(R.string.service_failed))
|
changeState(State.STOPPED, getString(R.string.service_failed))
|
||||||
stopRunner()
|
stopRunner()
|
||||||
changeState(State.STOPPED)
|
config = null
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
killProcesses()
|
if (config != null) {
|
||||||
|
|
||||||
var resolved: Boolean = false
|
killProcesses()
|
||||||
if (!InetAddressUtils.isIPv4Address(config.proxy) &&
|
|
||||||
!InetAddressUtils.isIPv6Address(config.proxy)) {
|
var resolved: Boolean = false
|
||||||
Utils.resolve(config.proxy, enableIPv6 = true) match {
|
if (!InetAddressUtils.isIPv4Address(config.proxy) &&
|
||||||
case Some(a) =>
|
!InetAddressUtils.isIPv6Address(config.proxy)) {
|
||||||
config.proxy = a
|
Utils.resolve(config.proxy, enableIPv6 = true) match {
|
||||||
resolved = true
|
case Some(a) =>
|
||||||
case None => resolved = false
|
config.proxy = a
|
||||||
|
resolved = true
|
||||||
|
case None => resolved = false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resolved = true
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
resolved = true
|
|
||||||
}
|
|
||||||
|
|
||||||
hasRedirectSupport = Utils.getHasRedirectSupport
|
hasRedirectSupport = Utils.getHasRedirectSupport
|
||||||
|
|
||||||
if (resolved && handleConnection) {
|
if (resolved && handleConnection) {
|
||||||
notifyForegroundAlert(getString(R.string.forward_success),
|
notifyForegroundAlert(getString(R.string.forward_success),
|
||||||
getString(R.string.service_running).format(config.profileName))
|
getString(R.string.service_running).format(config.profileName))
|
||||||
changeState(State.CONNECTED)
|
changeState(State.CONNECTED)
|
||||||
} else {
|
} else {
|
||||||
notifyAlert(getString(R.string.forward_fail), getString(R.string.service_failed))
|
changeState(State.STOPPED, getString(R.string.service_failed))
|
||||||
stopRunner()
|
stopRunner()
|
||||||
changeState(State.STOPPED)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -550,12 +525,11 @@ class ShadowsocksNatService extends Service with BaseService {
|
|||||||
// change the state
|
// change the state
|
||||||
changeState(State.STOPPED)
|
changeState(State.STOPPED)
|
||||||
|
|
||||||
// stop the tracker
|
// send event
|
||||||
EasyTracker
|
application.tracker.send(new HitBuilders.EventBuilder()
|
||||||
.getInstance(this)
|
.setCategory(TAG)
|
||||||
.send(MapBuilder
|
.setAction("stop")
|
||||||
.createEvent(TAG, "stop", getVersionName, 0L)
|
.setLabel(getVersionName)
|
||||||
.set(Fields.SESSION_CONTROL, "stop")
|
|
||||||
.build())
|
.build())
|
||||||
|
|
||||||
// reset timer
|
// reset timer
|
||||||
@@ -564,13 +538,6 @@ class ShadowsocksNatService extends Service with BaseService {
|
|||||||
timer = null
|
timer = null
|
||||||
}
|
}
|
||||||
|
|
||||||
// clean up context
|
|
||||||
stopForegroundCompat(1)
|
|
||||||
if (receiver != null) {
|
|
||||||
unregisterReceiver(receiver)
|
|
||||||
receiver = null
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset NAT
|
// reset NAT
|
||||||
killProcesses()
|
killProcesses()
|
||||||
|
|
||||||
@@ -578,6 +545,14 @@ class ShadowsocksNatService extends Service with BaseService {
|
|||||||
if (callbackCount == 0) {
|
if (callbackCount == 0) {
|
||||||
stopSelf()
|
stopSelf()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clean up context
|
||||||
|
if (receiver != null) {
|
||||||
|
unregisterReceiver(receiver)
|
||||||
|
receiver = null
|
||||||
|
}
|
||||||
|
|
||||||
|
stopForegroundCompat(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
override def stopBackgroundService() {
|
override def stopBackgroundService() {
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ class ShadowsocksRunnerActivity extends Activity {
|
|||||||
deattachService()
|
deattachService()
|
||||||
if (receiver != null) {
|
if (receiver != null) {
|
||||||
unregisterReceiver(receiver)
|
unregisterReceiver(receiver)
|
||||||
receiver = null;
|
receiver = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,25 +39,24 @@
|
|||||||
|
|
||||||
package com.github.shadowsocks
|
package com.github.shadowsocks
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
import java.net.InetAddress
|
||||||
|
|
||||||
import android.app._
|
import android.app._
|
||||||
import android.content._
|
import android.content._
|
||||||
import android.content.pm.PackageInfo
|
import android.content.pm.{PackageInfo, PackageManager}
|
||||||
import android.content.pm.PackageManager
|
import android.net.VpnService
|
||||||
import android.os._
|
import android.os._
|
||||||
import android.support.v4.app.NotificationCompat
|
import android.support.v4.app.NotificationCompat
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.google.analytics.tracking.android.{Fields, MapBuilder, EasyTracker}
|
import com.github.shadowsocks.aidl.Config
|
||||||
import android.net.VpnService
|
|
||||||
import org.apache.http.conn.util.InetAddressUtils
|
|
||||||
import android.os.Message
|
|
||||||
import scala.concurrent.ops._
|
|
||||||
import org.apache.commons.net.util.SubnetUtils
|
|
||||||
import com.github.shadowsocks.utils._
|
import com.github.shadowsocks.utils._
|
||||||
import scala.Some
|
import com.google.android.gms.analytics.HitBuilders
|
||||||
import com.github.shadowsocks.aidl.{IShadowsocksService, Config}
|
import org.apache.commons.net.util.SubnetUtils
|
||||||
|
import org.apache.http.conn.util.InetAddressUtils
|
||||||
|
|
||||||
import scala.collection.mutable.ArrayBuffer
|
import scala.collection.mutable.ArrayBuffer
|
||||||
import java.io.File
|
import scala.concurrent.ops._
|
||||||
import java.net.InetAddress
|
|
||||||
|
|
||||||
class ShadowsocksVpnService extends VpnService with BaseService {
|
class ShadowsocksVpnService extends VpnService with BaseService {
|
||||||
|
|
||||||
@@ -73,7 +72,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
|||||||
var apps: Array[ProxiedApp] = null
|
var apps: Array[ProxiedApp] = null
|
||||||
var config: Config = null
|
var config: Config = null
|
||||||
|
|
||||||
val handler: Handler = new Handler()
|
private lazy val application = getApplication.asInstanceOf[ShadowsocksApplication]
|
||||||
|
|
||||||
def isByass(net: SubnetUtils): Boolean = {
|
def isByass(net: SubnetUtils): Boolean = {
|
||||||
val info = net.getInfo
|
val info = net.getInfo
|
||||||
@@ -118,13 +117,8 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
|||||||
|
|
||||||
def startVpn() {
|
def startVpn() {
|
||||||
|
|
||||||
val openIntent: Intent = new Intent(this, classOf[Shadowsocks])
|
|
||||||
openIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
|
||||||
val configIntent = PendingIntent.getActivity(this, 0, openIntent, 0)
|
|
||||||
|
|
||||||
val builder = new Builder()
|
val builder = new Builder()
|
||||||
builder
|
builder
|
||||||
.setConfigureIntent(configIntent)
|
|
||||||
.setSession(config.profileName)
|
.setSession(config.profileName)
|
||||||
.setMtu(VPN_MTU)
|
.setMtu(VPN_MTU)
|
||||||
.addAddress(PRIVATE_VLAN.format("1"), 24)
|
.addAddress(PRIVATE_VLAN.format("1"), 24)
|
||||||
@@ -220,22 +214,6 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
def notifyAlert(title: String, info: String) {
|
|
||||||
val openIntent: Intent = new Intent(this, classOf[Shadowsocks])
|
|
||||||
openIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
|
||||||
val contentIntent: PendingIntent = PendingIntent.getActivity(this, 0, openIntent, 0)
|
|
||||||
val builder: NotificationCompat.Builder = new NotificationCompat.Builder(this)
|
|
||||||
builder
|
|
||||||
.setSmallIcon(R.drawable.ic_stat_shadowsocks)
|
|
||||||
.setWhen(0)
|
|
||||||
.setTicker(title)
|
|
||||||
.setContentTitle(getString(R.string.app_name))
|
|
||||||
.setContentText(info)
|
|
||||||
.setContentIntent(contentIntent)
|
|
||||||
.setAutoCancel(true)
|
|
||||||
notificationManager.notify(1, builder.build)
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onBind(intent: Intent): IBinder = {
|
override def onBind(intent: Intent): IBinder = {
|
||||||
val action = intent.getAction
|
val action = intent.getAction
|
||||||
if (VpnService.SERVICE_INTERFACE == action) {
|
if (VpnService.SERVICE_INTERFACE == action) {
|
||||||
@@ -255,14 +233,6 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
|||||||
.asInstanceOf[NotificationManager]
|
.asInstanceOf[NotificationManager]
|
||||||
}
|
}
|
||||||
|
|
||||||
override def onStartCommand(intent: Intent, flags: Int, startId: Int): Int = {
|
|
||||||
Service.START_STICKY
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onTaskRemoved(intent: Intent) {
|
|
||||||
stopRunner()
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onRevoke() {
|
override def onRevoke() {
|
||||||
stopRunner()
|
stopRunner()
|
||||||
}
|
}
|
||||||
@@ -289,12 +259,11 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// start the tracker
|
// send event
|
||||||
EasyTracker
|
application.tracker.send(new HitBuilders.EventBuilder()
|
||||||
.getInstance(this)
|
.setCategory(TAG)
|
||||||
.send(MapBuilder
|
.setAction("start")
|
||||||
.createEvent(TAG, "start", getVersionName, 0L)
|
.setLabel(getVersionName)
|
||||||
.set(Fields.SESSION_CONTROL, "start")
|
|
||||||
.build())
|
.build())
|
||||||
|
|
||||||
// register close receiver
|
// register close receiver
|
||||||
@@ -311,41 +280,42 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
|||||||
|
|
||||||
spawn {
|
spawn {
|
||||||
if (config.proxy == "198.199.101.152") {
|
if (config.proxy == "198.199.101.152") {
|
||||||
val container = getApplication.asInstanceOf[ShadowsocksApplication].tagContainer
|
val holder = getApplication.asInstanceOf[ShadowsocksApplication].containerHolder
|
||||||
try {
|
try {
|
||||||
config = ConfigUtils.getPublicConfig(getBaseContext, container, config)
|
config = ConfigUtils.getPublicConfig(getBaseContext, holder.getContainer, config)
|
||||||
} catch {
|
} catch {
|
||||||
case ex: Exception =>
|
case ex: Exception =>
|
||||||
notifyAlert(getString(R.string.forward_fail), getString(R.string.service_failed))
|
changeState(State.STOPPED, getString(R.string.service_failed))
|
||||||
stopRunner()
|
stopRunner()
|
||||||
changeState(State.STOPPED)
|
config = null
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset the context
|
if (config != null) {
|
||||||
killProcesses()
|
|
||||||
|
|
||||||
// Resolve the server address
|
// reset the context
|
||||||
var resolved: Boolean = false
|
killProcesses()
|
||||||
if (!InetAddressUtils.isIPv4Address(config.proxy) &&
|
|
||||||
!InetAddressUtils.isIPv6Address(config.proxy)) {
|
// Resolve the server address
|
||||||
Utils.resolve(config.proxy, enableIPv6 = true) match {
|
var resolved: Boolean = false
|
||||||
case Some(addr) =>
|
if (!InetAddressUtils.isIPv4Address(config.proxy) &&
|
||||||
config.proxy = addr
|
!InetAddressUtils.isIPv6Address(config.proxy)) {
|
||||||
resolved = true
|
Utils.resolve(config.proxy, enableIPv6 = true) match {
|
||||||
case None => resolved = false
|
case Some(addr) =>
|
||||||
|
config.proxy = addr
|
||||||
|
resolved = true
|
||||||
|
case None => resolved = false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resolved = true
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
resolved = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resolved && handleConnection) {
|
if (resolved && handleConnection) {
|
||||||
changeState(State.CONNECTED)
|
changeState(State.CONNECTED)
|
||||||
} else {
|
} else {
|
||||||
notifyAlert(getString(R.string.forward_fail), getString(R.string.service_failed))
|
changeState(State.STOPPED, getString(R.string.service_failed))
|
||||||
changeState(State.STOPPED)
|
stopRunner()
|
||||||
stopRunner()
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -355,20 +325,13 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
|||||||
// channge the state
|
// channge the state
|
||||||
changeState(State.STOPPED)
|
changeState(State.STOPPED)
|
||||||
|
|
||||||
// stop the tracker
|
// send event
|
||||||
EasyTracker
|
application.tracker.send(new HitBuilders.EventBuilder()
|
||||||
.getInstance(this)
|
.setCategory(TAG)
|
||||||
.send(MapBuilder
|
.setAction("stop")
|
||||||
.createEvent(TAG, "stop", getVersionName, 0L)
|
.setLabel(getVersionName)
|
||||||
.set(Fields.SESSION_CONTROL, "stop")
|
|
||||||
.build())
|
.build())
|
||||||
|
|
||||||
// clean up the context
|
|
||||||
if (receiver != null) {
|
|
||||||
unregisterReceiver(receiver)
|
|
||||||
receiver = null
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset VPN
|
// reset VPN
|
||||||
killProcesses()
|
killProcesses()
|
||||||
|
|
||||||
@@ -378,13 +341,16 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
|||||||
conn = null
|
conn = null
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset notifications
|
|
||||||
notificationManager.cancel(1)
|
|
||||||
|
|
||||||
// stop the service if no callback registered
|
// stop the service if no callback registered
|
||||||
if (callbackCount == 0) {
|
if (callbackCount == 0) {
|
||||||
stopSelf()
|
stopSelf()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clean up the context
|
||||||
|
if (receiver != null) {
|
||||||
|
unregisterReceiver(receiver)
|
||||||
|
receiver = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override def stopBackgroundService() {
|
override def stopBackgroundService() {
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ package com.github.shadowsocks.utils
|
|||||||
|
|
||||||
import android.content.{SharedPreferences, Context}
|
import android.content.{SharedPreferences, Context}
|
||||||
import com.github.shadowsocks.ShadowsocksApplication
|
import com.github.shadowsocks.ShadowsocksApplication
|
||||||
import com.google.tagmanager.Container
|
import com.google.android.gms.tagmanager.Container
|
||||||
import scalaj.http.{HttpOptions, Http}
|
import scalaj.http.{HttpOptions, Http}
|
||||||
import com.github.shadowsocks.aidl.Config
|
import com.github.shadowsocks.aidl.Config
|
||||||
|
|
||||||
@@ -143,8 +143,8 @@ object ConfigUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def refresh(context: Context) {
|
def refresh(context: Context) {
|
||||||
val container = context.getApplicationContext.asInstanceOf[ShadowsocksApplication].tagContainer
|
val holder = context.getApplicationContext.asInstanceOf[ShadowsocksApplication].containerHolder
|
||||||
if (container != null) container.refresh()
|
if (holder != null) holder.refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
def getPublicConfig(context: Context, container: Container, config: Config): Config = {
|
def getPublicConfig(context: Context, container: Container, config: Config): Config = {
|
||||||
|
|||||||
@@ -57,7 +57,10 @@ object Console {
|
|||||||
.open(new OnCommandResultListener {
|
.open(new OnCommandResultListener {
|
||||||
override def onCommandResult(commandCode: Int, exitCode: Int,
|
override def onCommandResult(commandCode: Int, exitCode: Int,
|
||||||
output: util.List[String]) {
|
output: util.List[String]) {
|
||||||
if (exitCode < 0) shell = null
|
if (exitCode < 0) {
|
||||||
|
shell.close()
|
||||||
|
shell = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -82,8 +85,9 @@ object Console {
|
|||||||
if (shell == null) {
|
if (shell == null) {
|
||||||
openShell()
|
openShell()
|
||||||
}
|
}
|
||||||
shell.addCommand(commands)
|
val ts = shell
|
||||||
shell.waitForIdle()
|
ts.addCommand(commands)
|
||||||
|
ts.waitForIdle()
|
||||||
}
|
}
|
||||||
|
|
||||||
def runRootCommand(command: String): String = runRootCommand(Array(command))
|
def runRootCommand(command: String): String = runRootCommand(Array(command))
|
||||||
@@ -95,11 +99,13 @@ object Console {
|
|||||||
if (rootShell == null) {
|
if (rootShell == null) {
|
||||||
openRootShell()
|
openRootShell()
|
||||||
}
|
}
|
||||||
|
val ts = rootShell
|
||||||
val sb = new StringBuilder
|
val sb = new StringBuilder
|
||||||
rootShell.addCommand(commands, 0, new OnCommandResultListener {
|
ts.addCommand(commands, 0, new OnCommandResultListener {
|
||||||
override def onCommandResult(commandCode: Int, exitCode: Int,
|
override def onCommandResult(commandCode: Int, exitCode: Int,
|
||||||
output: util.List[String]) {
|
output: util.List[String]) {
|
||||||
if (exitCode < 0) {
|
if (exitCode < 0) {
|
||||||
|
rootShell.close()
|
||||||
rootShell = null
|
rootShell = null
|
||||||
} else {
|
} else {
|
||||||
import scala.collection.JavaConversions._
|
import scala.collection.JavaConversions._
|
||||||
@@ -107,7 +113,7 @@ object Console {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if (rootShell.waitForIdle()) sb.toString()
|
if (ts.waitForIdle()) sb.toString()
|
||||||
else null
|
else null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||