diff --git a/AndroidManifest.xml b/AndroidManifest.xml index f14f04c3..1294e97e 100755 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -2,12 +2,13 @@ + android:versionCode="4" + android:versionName="1.1"> + + + + + + + diff --git a/assets/local.js b/assets/local.js index cdb3937a..bad00dda 100644 --- a/assets/local.js +++ b/assets/local.js @@ -164,6 +164,11 @@ console.log = function() {}; + var pid = ""+process.pid; // need to turn into a string + fs.writeFile('/data/data/com.github.shadowsocks/shadowsocks.pid', pid, function (err) { + // Ignore + }); + console.log("calculating ciphers"); tables = getTable(KEY); @@ -332,11 +337,6 @@ }); }); - var pid = ""+process.pid; // need to turn into a string - fs.writeFile('/data/data/com.github.shadowsocks/shadowsocks.pid', pid, function (err) { - // Ignore - }); - server.listen(PORT, function() { return console.log("server listening at port " + PORT); }); diff --git a/pom.xml b/pom.xml index a200a095..2fd1e3fa 100755 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.github.shadowsocks shadowsocks - 1.0.2 + 1.1 apk Shadowsocks diff --git a/res/xml/shadowsocks_preference.xml b/res/xml/shadowsocks_preference.xml index 9016fa4a..53c31d18 100755 --- a/res/xml/shadowsocks_preference.xml +++ b/res/xml/shadowsocks_preference.xml @@ -4,6 +4,7 @@ @@ -11,24 +12,28 @@ - + + diff --git a/src/com/github/shadowsocks/Shadowsocks.java b/src/com/github/shadowsocks/Shadowsocks.java index e697586a..9ed19629 100644 --- a/src/com/github/shadowsocks/Shadowsocks.java +++ b/src/com/github/shadowsocks/Shadowsocks.java @@ -103,13 +103,10 @@ public class Shadowsocks extends PreferenceActivity implements private static ProgressDialog mProgressDialog = null; - private CheckBoxPreference isGlobalProxyCheck; private EditTextPreference proxyText; private EditTextPreference portText; private EditTextPreference remotePortText; private EditTextPreference sitekeyText; - private CheckBoxPreference isGFWListCheck; - private CheckBoxPreference isRunningCheck; private Preference proxyedApps; private CheckBoxPreference isBypassAppsCheck; @@ -159,32 +156,6 @@ public class Shadowsocks extends PreferenceActivity implements } - private void disableAll() { - proxyText.setEnabled(false); - portText.setEnabled(false); - remotePortText.setEnabled(false); - sitekeyText.setEnabled(false); - proxyedApps.setEnabled(false); - isGFWListCheck.setEnabled(false); - isBypassAppsCheck.setEnabled(false); - - isGlobalProxyCheck.setEnabled(false); - } - - private void enableAll() { - proxyText.setEnabled(true); - portText.setEnabled(true); - remotePortText.setEnabled(true); - sitekeyText.setEnabled(true); - isGlobalProxyCheck.setEnabled(true); - isGFWListCheck.setEnabled(true); - if (!isGlobalProxyCheck.isChecked()) { - proxyedApps.setEnabled(true); - isBypassAppsCheck.setEnabled(true); - } - - } - private boolean isTextEmpty(String s, String msg) { if (s == null || s.length() <= 0) { showAToast(msg); @@ -208,9 +179,6 @@ public class Shadowsocks extends PreferenceActivity implements sitekeyText = (EditTextPreference) findPreference("sitekey"); proxyedApps = findPreference("proxyedApps"); - isRunningCheck = (CheckBoxPreference) findPreference("isRunning"); - isGlobalProxyCheck = (CheckBoxPreference) findPreference("isGlobalProxy"); - isGFWListCheck = (CheckBoxPreference) findPreference("isGFWList"); isBypassAppsCheck = (CheckBoxPreference) findPreference("isBypassApps"); if (mProgressDialog == null) @@ -350,23 +318,14 @@ public class Shadowsocks extends PreferenceActivity implements SharedPreferences settings = PreferenceManager .getDefaultSharedPreferences(this); - if (settings.getBoolean("isSystemProxy", false)) { - isGlobalProxyCheck.setEnabled(false); - isGFWListCheck.setEnabled(false); + if (settings.getBoolean("isGlobalProxy", false)) { proxyedApps.setEnabled(false); isBypassAppsCheck.setEnabled(false); } else { - if (settings.getBoolean("isGlobalProxy", false)) { - proxyedApps.setEnabled(false); - isBypassAppsCheck.setEnabled(false); - } else { - proxyedApps.setEnabled(true); - isBypassAppsCheck.setEnabled(true); - } + proxyedApps.setEnabled(true); + isBypassAppsCheck.setEnabled(true); } - sitekeyText.setEnabled(true); - Editor edit = settings.edit(); if (ShadowsocksService.isServiceStarted()) { @@ -386,14 +345,6 @@ public class Shadowsocks extends PreferenceActivity implements edit.commit(); - if (settings.getBoolean("isRunning", false)) { - isRunningCheck.setChecked(true); - disableAll(); - } else { - isRunningCheck.setChecked(false); - enableAll(); - } - // Setup the initial values if (!settings.getString("sitekey", "").equals("")) @@ -448,15 +399,6 @@ public class Shadowsocks extends PreferenceActivity implements } } - if (key.equals("isRunning")) { - if (settings.getBoolean("isRunning", false)) { - disableAll(); - isRunningCheck.setChecked(true); - } else { - isRunningCheck.setChecked(false); - enableAll(); - } - } if (key.equals("remotePort")) if (settings.getString("remotePort", "").equals("")) diff --git a/src/com/github/shadowsocks/ShadowsocksReceiver.java b/src/com/github/shadowsocks/ShadowsocksReceiver.java new file mode 100644 index 00000000..2f67afe2 --- /dev/null +++ b/src/com/github/shadowsocks/ShadowsocksReceiver.java @@ -0,0 +1,47 @@ +package com.github.shadowsocks; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.preference.PreferenceManager; + +public class ShadowsocksReceiver extends BroadcastReceiver { + + private static final String TAG = "Shadowsocks"; + + @Override + public void onReceive(Context context, Intent intent) { + + SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); + String versionName; + try { + versionName = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName; + } catch (PackageManager.NameNotFoundException e) { + versionName = "NONE"; + } + + final boolean isAutoConnect = settings.getBoolean("isAutoConnect", false); + final boolean isInstalled = settings.getBoolean(versionName, false); + + if (isAutoConnect && isInstalled) { + final String portText = settings.getString("port", ""); + if (portText == null || portText.length() <= 0) { + return; + } + try { + int port = Integer.valueOf(portText); + if (port <= 1024) { + return; + } + } catch (Exception e) { + return; + } + + Intent it = new Intent(context, ShadowsocksService.class); + context.startService(it); + } + } + +} diff --git a/src/com/github/shadowsocks/ShadowsocksService.java b/src/com/github/shadowsocks/ShadowsocksService.java index 144f0f59..3c999777 100755 --- a/src/com/github/shadowsocks/ShadowsocksService.java +++ b/src/com/github/shadowsocks/ShadowsocksService.java @@ -56,8 +56,7 @@ import android.preference.PreferenceManager; import android.util.Log; import com.google.analytics.tracking.android.EasyTracker; -import java.io.DataOutputStream; -import java.io.IOException; +import java.io.*; import java.lang.ref.WeakReference; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -183,7 +182,22 @@ public class ShadowsocksService extends Service { return isServiceStarted; } - public void startShadowsocksDaemon() { + private int getPid(String name) { + try { + BufferedReader reader = new BufferedReader(new FileReader(BASE + name + ".pid")); + final String line = reader.readLine(); + return Integer.valueOf(line); + } catch (FileNotFoundException e) { + Log.e(TAG, "Cannot open pid file: " + name); + } catch (IOException e) { + Log.e(TAG, "Cannot read pid file: " + name); + } catch (NumberFormatException e) { + Log.e(TAG, "Invalid pid", e); + } + return -1; + } + + private void startShadowsocksDaemon() { new Thread() { @Override public void run() { @@ -195,9 +209,9 @@ public class ShadowsocksService extends Service { }.start(); } - public void startDnsDaemon() { + private void startDnsDaemon() { final String cmd = BASE + "pdnsd -c " + BASE + "pdnsd.conf"; - Utils.runRootCommand(cmd); + Utils.runCommand(cmd); } private String getVersionName() { @@ -277,7 +291,26 @@ public class ShadowsocksService extends Service { BASE, BASE, BASE); Utils.runRootCommand("echo \"" + conf + "\" > " + BASE + "redsocks.conf\n" + cmd); + } + private boolean waitForProcess(final String name) { + final int pid = getPid(name); + if (pid == -1) return false; + + Exec.hangupProcessGroup(-pid); + Thread t = new Thread() { + @Override + public void run() { + Exec.waitFor(-pid); + Log.d(TAG, "Successfully exit pid: " + pid); + } + }; + t.start(); + try { + t.join(300); + } catch (InterruptedException ignored) { + } + return !t.isAlive(); } /** @@ -436,9 +469,13 @@ public class ShadowsocksService extends Service { private void onDisconnect() { Utils.runRootCommand(Utils.getIptables() + " -t nat -F OUTPUT"); StringBuilder sb = new StringBuilder(); - sb.append("kill -9 `cat /data/data/com.github.shadowsocks/pdnsd.pid`").append("\n"); sb.append("kill -9 `cat /data/data/com.github.shadowsocks/redsocks.pid`").append("\n"); - sb.append("kill -9 `cat /data/data/com.github.shadowsocks/shadowsocks.pid`").append("\n"); + if (!waitForProcess("pdnsd")) { + sb.append("kill -9 `cat /data/data/com.github.shadowsocks/pdnsd.pid`").append("\n"); + } + if (!waitForProcess("shadowsocks")) { + sb.append("kill -9 `cat /data/data/com.github.shadowsocks/shadowsocks.pid`").append("\n"); + } Utils.runRootCommand(sb.toString()); }