Commit 67fab039 authored by Mygod's avatar Mygod Committed by Max Lv

Let Android system extract native libraries

parent bf89e202
...@@ -7,19 +7,9 @@ function try () { ...@@ -7,19 +7,9 @@ function try () {
# Build native binaries # Build native binaries
pushd src/main pushd src/main
try $ANDROID_NDK_HOME/ndk-build -j8 try $ANDROID_NDK_HOME/ndk-build -j8
# Clean up old binaries (no longer used)
rm -rf assets/armeabi-v7a rm -rf assets/armeabi-v7a
rm -rf assets/x86 rm -rf assets/x86
mkdir -p assets/armeabi-v7a
mkdir -p assets/x86
#copy executables
for app in pdnsd redsocks ss-local ss-tunnel tun2socks
do
echo $app
try mv libs/armeabi-v7a/$app assets/armeabi-v7a/
try mv libs/x86/$app assets/x86/
done
popd popd
# Build kcptun # Build kcptun
......
...@@ -58,12 +58,12 @@ go get ...@@ -58,12 +58,12 @@ go get
echo "Cross compile kcptun for arm" echo "Cross compile kcptun for arm"
try env CGO_ENABLED=1 CC=$ANDROID_ARM_CC GOOS=android GOARCH=arm GOARM=7 go build -ldflags="-s -w" try env CGO_ENABLED=1 CC=$ANDROID_ARM_CC GOOS=android GOARCH=arm GOARM=7 go build -ldflags="-s -w"
try $ANDROID_ARM_STRIP client try $ANDROID_ARM_STRIP client
try mv client $DIR/../src/main/assets/armeabi-v7a/kcptun try mv client $DIR/../src/main/libs/armeabi-v7a/libkcptun.so
echo "Cross compile kcptun for x86" echo "Cross compile kcptun for x86"
try env CGO_ENABLED=1 CC=$ANDROID_X86_CC GOOS=android GOARCH=386 go build -ldflags="-s -w" try env CGO_ENABLED=1 CC=$ANDROID_X86_CC GOOS=android GOARCH=386 go build -ldflags="-s -w"
try $ANDROID_X86_STRIP client try $ANDROID_X86_STRIP client
try mv client $DIR/../src/main/assets/x86/kcptun try mv client $DIR/../src/main/libs/x86/libkcptun.so
popd popd
echo "Successfully build kcptun" echo "Successfully build kcptun"
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
<application <application
android:allowBackup="true" android:allowBackup="true"
android:extractNativeLibs="false"
android:name=".ShadowsocksApplication" android:name=".ShadowsocksApplication"
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
......
...@@ -44,7 +44,6 @@ public class System { ...@@ -44,7 +44,6 @@ public class System {
} }
public static native int exec(String cmd); public static native int exec(String cmd);
public static native String getABI();
public static native int sendfd(int fd, String path); public static native int sendfd(int fd, String path);
public static native void jniclose(int fd); public static native void jniclose(int fd);
} }
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
LOCAL_PATH := $(call my-dir) LOCAL_PATH := $(call my-dir)
ROOT_PATH := $(LOCAL_PATH) ROOT_PATH := $(LOCAL_PATH)
BUILD_SHARED_EXECUTABLE := $(LOCAL_PATH)/build-shared-executable.mk
######################################################## ########################################################
## libsodium ## libsodium
######################################################## ########################################################
...@@ -358,7 +360,7 @@ LOCAL_CFLAGS := -O2 -std=gnu99 -DUSE_IPTABLES \ ...@@ -358,7 +360,7 @@ LOCAL_CFLAGS := -O2 -std=gnu99 -DUSE_IPTABLES \
-I$(LOCAL_PATH)/libevent/include \ -I$(LOCAL_PATH)/libevent/include \
-I$(LOCAL_PATH)/libevent -I$(LOCAL_PATH)/libevent
include $(BUILD_EXECUTABLE) include $(BUILD_SHARED_EXECUTABLE)
######################################################## ########################################################
## pdnsd ## pdnsd
...@@ -375,7 +377,7 @@ LOCAL_CFLAGS := -DANDROID -Wall -O2 -I$(LOCAL_PATH)/pdnsd \ ...@@ -375,7 +377,7 @@ LOCAL_CFLAGS := -DANDROID -Wall -O2 -I$(LOCAL_PATH)/pdnsd \
LOCAL_STATIC_LIBRARIES := libancillary LOCAL_STATIC_LIBRARIES := libancillary
LOCAL_LDLIBS := -llog LOCAL_LDLIBS := -llog
include $(BUILD_EXECUTABLE) include $(BUILD_SHARED_EXECUTABLE)
######################################################## ########################################################
## shadowsocks-libev local ## shadowsocks-libev local
...@@ -410,7 +412,7 @@ LOCAL_STATIC_LIBRARIES := libev libmbedtls libipset libcork libudns \ ...@@ -410,7 +412,7 @@ LOCAL_STATIC_LIBRARIES := libev libmbedtls libipset libcork libudns \
LOCAL_LDLIBS := -llog LOCAL_LDLIBS := -llog
include $(BUILD_EXECUTABLE) include $(BUILD_SHARED_EXECUTABLE)
######################################################## ########################################################
## shadowsocks-libev tunnel ## shadowsocks-libev tunnel
...@@ -439,7 +441,7 @@ LOCAL_STATIC_LIBRARIES := libev libmbedtls libsodium libcork libudns libancillar ...@@ -439,7 +441,7 @@ LOCAL_STATIC_LIBRARIES := libev libmbedtls libsodium libcork libudns libancillar
LOCAL_LDLIBS := -llog LOCAL_LDLIBS := -llog
include $(BUILD_EXECUTABLE) include $(BUILD_SHARED_EXECUTABLE)
######################################################## ########################################################
## system ## system
...@@ -550,7 +552,7 @@ LOCAL_LDLIBS := -ldl -llog ...@@ -550,7 +552,7 @@ LOCAL_LDLIBS := -ldl -llog
LOCAL_SRC_FILES := $(addprefix badvpn/, $(TUN2SOCKS_SOURCES)) LOCAL_SRC_FILES := $(addprefix badvpn/, $(TUN2SOCKS_SOURCES))
include $(BUILD_EXECUTABLE) include $(BUILD_SHARED_EXECUTABLE)
######################################################## ########################################################
## mbed TLS ## mbed TLS
......
# Copyright (C) 2009 The Android Open Source Project
#
# 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.
#
# this file is included from Android.mk files to build a target-specific
# executable program
#
# Modified by @Mygod, based on:
# https://android.googlesource.com/platform/ndk/+/f2e98f8c066aed59caf61163d4b87c2b858f9814/build/core/build-shared-library.mk
# https://android.googlesource.com/platform/ndk/+/f2e98f8c066aed59caf61163d4b87c2b858f9814/build/core/build-executable.mk
LOCAL_BUILD_SCRIPT := BUILD_EXECUTABLE
LOCAL_MAKEFILE := $(local-makefile)
$(call check-defined-LOCAL_MODULE,$(LOCAL_BUILD_SCRIPT))
$(call check-LOCAL_MODULE,$(LOCAL_MAKEFILE))
$(call check-LOCAL_MODULE_FILENAME)
# we are building target objects
my := TARGET_
$(call handle-module-filename,lib,$(TARGET_SONAME_EXTENSION))
$(call handle-module-built)
LOCAL_MODULE_CLASS := EXECUTABLE
include $(BUILD_SYSTEM)/build-module.mk
...@@ -18,25 +18,6 @@ ...@@ -18,25 +18,6 @@
#define LOGW(...) do { __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__); } while(0) #define LOGW(...) do { __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__); } while(0)
#define LOGE(...) do { __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__); } while(0) #define LOGE(...) do { __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__); } while(0)
jstring Java_com_github_shadowsocks_system_getabi(JNIEnv *env, jobject thiz) {
AndroidCpuFamily family = android_getCpuFamily();
uint64_t features = android_getCpuFeatures();
const char *abi;
if (family == ANDROID_CPU_FAMILY_X86) {
abi = "x86";
} else if (family == ANDROID_CPU_FAMILY_MIPS) {
abi = "mips";
} else if (family == ANDROID_CPU_FAMILY_ARM) {
// if (features & ANDROID_CPU_ARM_FEATURE_ARMv7) {
abi = "armeabi-v7a";
// } else {
// abi = "armeabi";
// }
}
return env->NewStringUTF(abi);
}
jint Java_com_github_shadowsocks_system_exec(JNIEnv *env, jobject thiz, jstring cmd) { jint Java_com_github_shadowsocks_system_exec(JNIEnv *env, jobject thiz, jstring cmd) {
const char *cmd_str = env->GetStringUTFChars(cmd, 0); const char *cmd_str = env->GetStringUTFChars(cmd, 0);
...@@ -103,9 +84,7 @@ static JNINativeMethod method_table[] = { ...@@ -103,9 +84,7 @@ static JNINativeMethod method_table[] = {
{ "sendfd", "(ILjava/lang/String;)I", { "sendfd", "(ILjava/lang/String;)I",
(void*) Java_com_github_shadowsocks_system_sendfd }, (void*) Java_com_github_shadowsocks_system_sendfd },
{ "exec", "(Ljava/lang/String;)I", { "exec", "(Ljava/lang/String;)I",
(void*) Java_com_github_shadowsocks_system_exec }, (void*) Java_com_github_shadowsocks_system_exec }
{ "getABI", "()Ljava/lang/String;",
(void*) Java_com_github_shadowsocks_system_getabi }
}; };
......
...@@ -377,6 +377,7 @@ class MainActivity extends Activity with ServiceBoundContext with Drawer.OnDrawe ...@@ -377,6 +377,7 @@ class MainActivity extends Activity with ServiceBoundContext with Drawer.OnDrawe
override def handleMessage(msg: Message): Unit = if (dialog.isShowing && !isDestroyed) dialog.dismiss() override def handleMessage(msg: Message): Unit = if (dialog.isShowing && !isDestroyed) dialog.dismiss()
} }
Utils.ThrowableFuture { Utils.ThrowableFuture {
app.crashRecovery()
app.copyAssets() app.copyAssets()
handler.sendEmptyMessage(0) handler.sendEmptyMessage(0)
} }
......
...@@ -50,8 +50,6 @@ object ShadowsocksApplication { ...@@ -50,8 +50,6 @@ object ShadowsocksApplication {
var app: ShadowsocksApplication = _ var app: ShadowsocksApplication = _
private final val TAG = "ShadowsocksApplication" private final val TAG = "ShadowsocksApplication"
private val EXECUTABLES = Array(Executable.PDNSD, Executable.REDSOCKS, Executable.SS_TUNNEL, Executable.SS_LOCAL,
Executable.TUN2SOCKS, Executable.KCPTUN)
// The ones in Locale doesn't have script included // The ones in Locale doesn't have script included
private final lazy val SIMPLIFIED_CHINESE = private final lazy val SIMPLIFIED_CHINESE =
...@@ -180,25 +178,11 @@ class ShadowsocksApplication extends Application { ...@@ -180,25 +178,11 @@ class ShadowsocksApplication extends Application {
if (holder != null) holder.refresh() if (holder != null) holder.refresh()
} }
private def copyAssets(path: String) {
val assetManager = getAssets
var files: Array[String] = null
try files = assetManager.list(path) catch {
case e: IOException =>
Log.e(TAG, e.getMessage)
app.track(e)
}
if (files != null) for (file <- files)
autoClose(assetManager.open(if (path.nonEmpty) path + '/' + file else file))(in =>
autoClose(new FileOutputStream(getApplicationInfo.dataDir + '/' + file))(out =>
IOUtils.copy(in, out)))
}
def crashRecovery() { def crashRecovery() {
val cmd = new ArrayBuffer[String]() val cmd = new ArrayBuffer[String]()
for (task <- Array("ss-local", "ss-tunnel", "pdnsd", "redsocks", "tun2socks", "kcptun")) { for (task <- Executable.EXECUTABLES) {
cmd.append("killall %s".formatLocal(Locale.ENGLISH, task)) cmd.append("killall lib%s.so".formatLocal(Locale.ENGLISH, task))
cmd.append("rm -f %1$s/%2$s-nat.conf %1$s/%2$s-vpn.conf" cmd.append("rm -f %1$s/%2$s-nat.conf %1$s/%2$s-vpn.conf"
.formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir, task)) .formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir, task))
} }
...@@ -212,10 +196,16 @@ class ShadowsocksApplication extends Application { ...@@ -212,10 +196,16 @@ class ShadowsocksApplication extends Application {
} }
def copyAssets() { def copyAssets() {
crashRecovery() // ensure executables are killed before writing to them val assetManager = getAssets
copyAssets(System.getABI) var files: Array[String] = null
copyAssets("acl") try files = assetManager.list("acl") catch {
Shell.SH.run(EXECUTABLES.map("chmod 755 " + getApplicationInfo.dataDir + '/' + _)) case e: IOException =>
Log.e(TAG, e.getMessage)
app.track(e)
}
if (files != null) for (file <- files) autoClose(assetManager.open("acl/" + file))(in =>
autoClose(new FileOutputStream(getApplicationInfo.dataDir + '/' + file))(out =>
IOUtils.copy(in, out)))
editor.putInt(Key.currentVersionCode, BuildConfig.VERSION_CODE).apply() editor.putInt(Key.currentVersionCode, BuildConfig.VERSION_CODE).apply()
} }
......
...@@ -66,7 +66,7 @@ class ShadowsocksNatService extends BaseService { ...@@ -66,7 +66,7 @@ class ShadowsocksNatService extends BaseService {
p.println(conf) p.println(conf)
}) })
val cmd = ArrayBuffer[String](getApplicationInfo.dataDir + "/ss-local" val cmd = ArrayBuffer[String](getApplicationInfo.nativeLibraryDir + "/libss-local.so"
, "-b" , "127.0.0.1" , "-b" , "127.0.0.1"
, "-t" , "600" , "-t" , "600"
, "-P", getApplicationInfo.dataDir , "-P", getApplicationInfo.dataDir
...@@ -94,7 +94,7 @@ class ShadowsocksNatService extends BaseService { ...@@ -94,7 +94,7 @@ class ShadowsocksNatService extends BaseService {
profile.host profile.host
} }
val cmd = ArrayBuffer[String](getApplicationInfo.dataDir + "/kcptun" val cmd = ArrayBuffer[String](getApplicationInfo.nativeLibraryDir + "/libkcptun.so"
, "-r", host + ":" + profile.kcpPort , "-r", host + ":" + profile.kcpPort
, "-l", "127.0.0.1:" + (profile.localPort + 90)) , "-l", "127.0.0.1:" + (profile.localPort + 90))
try cmd ++= Utils.translateCommandline(profile.kcpcli) catch { try cmd ++= Utils.translateCommandline(profile.kcpcli) catch {
...@@ -114,7 +114,7 @@ class ShadowsocksNatService extends BaseService { ...@@ -114,7 +114,7 @@ class ShadowsocksNatService extends BaseService {
Utils.printToFile(new File(getApplicationInfo.dataDir + "/ss-tunnel-nat.conf"))(p => { Utils.printToFile(new File(getApplicationInfo.dataDir + "/ss-tunnel-nat.conf"))(p => {
p.println(conf) p.println(conf)
}) })
val cmd = ArrayBuffer[String](getApplicationInfo.dataDir + "/ss-tunnel" val cmd = ArrayBuffer[String](getApplicationInfo.nativeLibraryDir + "/libss-tunnel.so"
, "-u" , "-u"
, "-t" , "10" , "-t" , "10"
, "-b" , "127.0.0.1" , "-b" , "127.0.0.1"
...@@ -142,7 +142,7 @@ class ShadowsocksNatService extends BaseService { ...@@ -142,7 +142,7 @@ class ShadowsocksNatService extends BaseService {
Utils.printToFile(new File(getApplicationInfo.dataDir + "/ss-tunnel-nat.conf"))(p => { Utils.printToFile(new File(getApplicationInfo.dataDir + "/ss-tunnel-nat.conf"))(p => {
p.println(conf) p.println(conf)
}) })
val cmdBuf = ArrayBuffer[String](getApplicationInfo.dataDir + "/ss-tunnel" val cmdBuf = ArrayBuffer[String](getApplicationInfo.nativeLibraryDir + "/libss-tunnel.so"
, "-t" , "10" , "-t" , "10"
, "-b" , "127.0.0.1" , "-b" , "127.0.0.1"
, "-l" , (profile.localPort + 63).toString , "-l" , (profile.localPort + 63).toString
...@@ -179,7 +179,7 @@ class ShadowsocksNatService extends BaseService { ...@@ -179,7 +179,7 @@ class ShadowsocksNatService extends BaseService {
Utils.printToFile(new File(getApplicationInfo.dataDir + "/pdnsd-nat.conf"))(p => { Utils.printToFile(new File(getApplicationInfo.dataDir + "/pdnsd-nat.conf"))(p => {
p.println(conf) p.println(conf)
}) })
val cmd = Array(getApplicationInfo.dataDir + "/pdnsd", "-c", getApplicationInfo.dataDir + "/pdnsd-nat.conf") val cmd = Array(getApplicationInfo.nativeLibraryDir + "/libpdnsd.so", "-c", getApplicationInfo.dataDir + "/pdnsd-nat.conf")
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" ")) if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
...@@ -188,7 +188,7 @@ class ShadowsocksNatService extends BaseService { ...@@ -188,7 +188,7 @@ class ShadowsocksNatService extends BaseService {
def startRedsocksDaemon() { def startRedsocksDaemon() {
val conf = ConfigUtils.REDSOCKS.formatLocal(Locale.ENGLISH, profile.localPort) val conf = ConfigUtils.REDSOCKS.formatLocal(Locale.ENGLISH, profile.localPort)
val cmd = Array(getApplicationInfo.dataDir + "/redsocks", "-c", getApplicationInfo.dataDir + "/redsocks-nat.conf") val cmd = Array(getApplicationInfo.nativeLibraryDir + "/libredsocks.so", "-c", getApplicationInfo.dataDir + "/redsocks-nat.conf")
Utils.printToFile(new File(getApplicationInfo.dataDir + "/redsocks-nat.conf"))(p => { Utils.printToFile(new File(getApplicationInfo.dataDir + "/redsocks-nat.conf"))(p => {
p.println(conf) p.println(conf)
}) })
......
...@@ -182,7 +182,7 @@ class ShadowsocksVpnService extends VpnService with BaseService { ...@@ -182,7 +182,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
profile.host profile.host
} }
val cmd = ArrayBuffer(getApplicationInfo.dataDir + "/kcptun" val cmd = ArrayBuffer(getApplicationInfo.nativeLibraryDir + "/libkcptun.so"
, "-r", host + ":" + profile.kcpPort , "-r", host + ":" + profile.kcpPort
, "-l", "127.0.0.1:" + (profile.localPort + 90) , "-l", "127.0.0.1:" + (profile.localPort + 90)
, "--path", protectPath) , "--path", protectPath)
...@@ -204,7 +204,7 @@ class ShadowsocksVpnService extends VpnService with BaseService { ...@@ -204,7 +204,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
p.println(conf) p.println(conf)
}) })
val cmd = ArrayBuffer[String](getApplicationInfo.dataDir + "/ss-local", "-V", "-U" val cmd = ArrayBuffer[String](getApplicationInfo.nativeLibraryDir + "/libss-local.so", "-V", "-U"
, "-b", "127.0.0.1" , "-b", "127.0.0.1"
, "-t", "600" , "-t", "600"
, "-P", getApplicationInfo.dataDir , "-P", getApplicationInfo.dataDir
...@@ -231,7 +231,7 @@ class ShadowsocksVpnService extends VpnService with BaseService { ...@@ -231,7 +231,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
p.println(conf) p.println(conf)
}) })
val cmd = ArrayBuffer[String](getApplicationInfo.dataDir + "/ss-local", "-V" val cmd = ArrayBuffer[String](getApplicationInfo.nativeLibraryDir + "/libss-local.so", "-V"
, "-b", "127.0.0.1" , "-b", "127.0.0.1"
, "-t", "600" , "-t", "600"
, "-P", getApplicationInfo.dataDir , "-P", getApplicationInfo.dataDir
...@@ -266,7 +266,7 @@ class ShadowsocksVpnService extends VpnService with BaseService { ...@@ -266,7 +266,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
Utils.printToFile(new File(getApplicationInfo.dataDir + "/ss-tunnel-vpn.conf"))(p => { Utils.printToFile(new File(getApplicationInfo.dataDir + "/ss-tunnel-vpn.conf"))(p => {
p.println(conf) p.println(conf)
}) })
val cmd = ArrayBuffer[String](getApplicationInfo.dataDir + "/ss-tunnel" val cmd = ArrayBuffer[String](getApplicationInfo.nativeLibraryDir + "/libss-tunnel.so"
, "-V" , "-V"
, "-t", "10" , "-t", "10"
, "-b", "127.0.0.1" , "-b", "127.0.0.1"
...@@ -300,7 +300,7 @@ class ShadowsocksVpnService extends VpnService with BaseService { ...@@ -300,7 +300,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
Utils.printToFile(new File(getApplicationInfo.dataDir + "/pdnsd-vpn.conf"))(p => { Utils.printToFile(new File(getApplicationInfo.dataDir + "/pdnsd-vpn.conf"))(p => {
p.println(conf) p.println(conf)
}) })
val cmd = Array(getApplicationInfo.dataDir + "/pdnsd", "-c", getApplicationInfo.dataDir + "/pdnsd-vpn.conf") val cmd = Array(getApplicationInfo.nativeLibraryDir + "/libpdnsd.so", "-c", getApplicationInfo.dataDir + "/pdnsd-vpn.conf")
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" ")) if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
...@@ -358,7 +358,7 @@ class ShadowsocksVpnService extends VpnService with BaseService { ...@@ -358,7 +358,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
val fd = conn.getFd val fd = conn.getFd
var cmd = ArrayBuffer[String](getApplicationInfo.dataDir + "/tun2socks", var cmd = ArrayBuffer[String](getApplicationInfo.nativeLibraryDir + "/libtun2socks.so",
"--netif-ipaddr", PRIVATE_VLAN.formatLocal(Locale.ENGLISH, "2"), "--netif-ipaddr", PRIVATE_VLAN.formatLocal(Locale.ENGLISH, "2"),
"--netif-netmask", "255.255.255.0", "--netif-netmask", "255.255.255.0",
"--socks-server-addr", "127.0.0.1:" + profile.localPort, "--socks-server-addr", "127.0.0.1:" + profile.localPort,
......
...@@ -35,7 +35,7 @@ class KcpCliPreferenceDialogFragment extends EditTextPreferenceDialogFragment { ...@@ -35,7 +35,7 @@ class KcpCliPreferenceDialogFragment extends EditTextPreferenceDialogFragment {
super.onPrepareDialogBuilder(builder) super.onPrepareDialogBuilder(builder)
builder.setNeutralButton("?", ((_, _) => new AlertDialog.Builder(builder.getContext) builder.setNeutralButton("?", ((_, _) => new AlertDialog.Builder(builder.getContext)
.setTitle("?") .setTitle("?")
.setMessage(Shell.SH.run(builder.getContext.getApplicationInfo.dataDir + "/kcptun --help") .setMessage(Shell.SH.run(builder.getContext.getApplicationInfo.nativeLibraryDir + "/libkcptun.so --help")
.asScala .asScala
.dropWhile(line => line != "GLOBAL OPTIONS:") .dropWhile(line => line != "GLOBAL OPTIONS:")
.drop(1) .drop(1)
......
...@@ -27,6 +27,8 @@ object Executable { ...@@ -27,6 +27,8 @@ object Executable {
val SS_TUNNEL = "ss-tunnel" val SS_TUNNEL = "ss-tunnel"
val TUN2SOCKS = "tun2socks" val TUN2SOCKS = "tun2socks"
val KCPTUN = "kcptun" val KCPTUN = "kcptun"
val EXECUTABLES = Array(SS_LOCAL, SS_TUNNEL, PDNSD, REDSOCKS, TUN2SOCKS, KCPTUN)
} }
object ConfigUtils { object ConfigUtils {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment