Compare commits

...
35 Commits
Author SHA1 Message Date
Max Lv 398db4f407 Add back internal QR scanner. #1273 2017-06-05 09:27:59 +08:00
Max Lv 8208ac1510 Bump version 2017-06-03 08:48:14 +08:00
Max Lv 5542f463a6 Roll back to Google's barcode scanner 2017-06-03 08:44:12 +08:00
Mygod 095f4831db Remove duplicated files in Google Play services 2017-05-18 14:19:11 +08:00
Mygod ba75b7af75 Update Google Play services 2017-05-18 11:51:35 +08:00
Mygod d5dc3a8379 Change build toolchain for go to clang
Also adds helpful go-clean command.
2017-05-18 09:59:53 +08:00
Mygod 89ddc2f7c9 Use standard __ANDROID__ preprocessor macro 2017-05-18 09:59:42 +08:00
Mygod f721b57e00 Refine GuardedProcess to include stderr output 2017-05-18 09:59:29 +08:00
Mygod 3a785ab75e Fix Proguard warnings 2017-05-15 14:21:34 +08:00
Mygod b68689f731 Update okhttp 2017-05-15 14:05:18 +08:00
Max Lv cf2f17dfff Fix the protect socket issue on Android 4.4 2017-05-10 22:08:23 +08:00
Max Lv a64eb8ac58 Forward DNS packet to dnsgw 2017-05-10 22:08:23 +08:00
Mygod 9ab9230960 Merge strings from POEditor.com
Update strings.xml (POEditor.com)

Update strings.xml (POEditor.com)

Update strings.xml (POEditor.com)

Update strings.xml (POEditor.com)
2017-05-10 15:48:33 +08:00
Max Lv 8f6357d9cf Fix the dualstack issue on Android 4.4 2017-05-09 19:28:49 +08:00
Max Lv 73462b08af Remove debug info 2017-05-06 07:30:44 +08:00
Max Lv 6d07c03bc7 Fix #1186 2017-05-06 07:25:19 +08:00
Mygod 953f59ea43 Refine code style 2017-05-05 13:58:08 +08:00
Mygod 6df5179734 Remove redundant android-job proguard config 2017-05-05 13:53:04 +08:00
Mygod 2f312486a1 Avoid too many reschedules correctly 2017-05-05 13:43:19 +08:00
Mygod 88d5c01cb0 Update dependencies 2017-05-05 13:32:52 +08:00
Max Lv 2b05da3aff Bump version 2017-05-05 13:21:24 +08:00
Rallets c5a98a9b12 Limit abi for consistency (#1243) 2017-05-05 07:06:37 +08:00
Max Lv 5633ae7b21 Fix #1233 2017-04-29 18:51:54 +08:00
Max Lv 92af48f528 Fix #1236 2017-04-29 18:46:38 +08:00
Max Lv 59f02cfa53 Refine Firebase remote config 2017-04-28 16:50:41 +08:00
Max Lv bd782dae98 Avoid too many reschedules 2017-04-28 08:04:40 +08:00
Mygod ea738d17d7 Refine #1217 2017-04-24 11:51:47 +08:00
Mygod 915b1a74b1 Refine Firebase code 2017-04-24 11:37:47 +08:00
Mygod 9898ab88e0 Optimize firebase dependencies 2017-04-24 11:25:11 +08:00
Mygod c082a23c37 Update dependencies 2017-04-24 10:59:44 +08:00
Max Lv 6636cf815d Replace tag manager with firebase config 2017-04-23 23:11:44 +08:00
Max Lv 6df8f14fb2 Refine server name resolving 2017-04-23 21:49:01 +08:00
Max Lv 0b88881fa4 Update shadowsocks-libev 2017-04-20 14:10:09 +08:00
V.E.O 85532a6b48 Add multiple remote dns support and remove alternative dns in global mode (#1217)
* Add multiple remote dns support. Remove alternative dns in global mode.
* Remove a redundant comment
2017-04-14 23:32:14 -05:00
Mygod 93274ffb04 Update android-job 2017-04-14 00:08:17 +08:00
36 changed files with 360 additions and 150 deletions
+2 -2
View File
@@ -47,13 +47,13 @@ Translators can go to [POEditor](https://poeditor.com/join/project/u5VHO9vhSf) t
<ul>
<li>redsocks: <a href="https://github.com/shadowsocks/redsocks/blob/shadowsocks-android/README">APL 2.0</a></li>
<li>mbed TLS: <a href="https://github.com/ARMmbed/mbedtls/blob/development/LICENSE">APL 2.0</a></li>
<li>libevent: <a href="https://github.com/shadowsocks/shadowsocks-android/blob/master/src/main/jni/libevent/LICENSE">BSD</a></li>
<li>libevent: <a href="https://github.com/shadowsocks/libevent/blob/master/LICENSE">BSD</a></li>
<li>tun2socks: <a href="https://github.com/shadowsocks/badvpn/blob/shadowsocks-android/COPYING">BSD</a></li>
<li>pcre: <a href="https://android.googlesource.com/platform/external/pcre/+/master/dist2/LICENCE">BSD</a></li>
<li>libancillary: <a href="https://github.com/shadowsocks/libancillary/blob/shadowsocks-android/COPYING">BSD</a></li>
<li>shadowsocks-libev: <a href="https://github.com/shadowsocks/shadowsocks-libev/blob/master/LICENSE">GPLv3</a></li>
<li>overture: <a href="https://github.com/shawn1m/overture/blob/master/LICENSE">MIT</a></li>
<li>libev: <a href="https://github.com/shadowsocks/shadowsocks-libev/blob/master/libev/LICENSE">GPLv2</a></li>
<li>libev: <a href="https://github.com/shadowsocks/libev/blob/master/LICENSE">GPLv2</a></li>
<li>libsodium: <a href="https://github.com/jedisct1/libsodium/blob/master/LICENSE">ISC</a></li>
<li>libudns: <a href="https://github.com/shadowsocks/libudns/blob/master/COPYING.LGPL">LGPL</a></li>
</ul>
+2 -1
View File
@@ -10,6 +10,7 @@ lazy val commonSettings = Seq(
javacOptions ++= "-source" :: "1.7" :: "-target" :: "1.7" :: Nil,
scalacOptions ++= "-target:jvm-1.7" :: "-Xexperimental" :: Nil,
ndkArgs := "-j" :: java.lang.Runtime.getRuntime.availableProcessors.toString :: Nil,
ndkAbiFilter := Seq("armeabi-v7a", "arm64-v8a", "x86"),
proguardVersion := "5.3.3",
proguardCache := Seq(),
@@ -20,7 +21,7 @@ lazy val commonSettings = Seq(
resConfigs := Seq("ja", "ko", "ru", "zh-rCN", "zh-rTW")
)
val supportLibsVersion = "25.2.0"
val supportLibsVersion = "25.3.1"
lazy val root = Project(id = "shadowsocks-android", base = file("."))
.settings(commonSettings)
.aggregate(plugin, mobile)
+27 -9
View File
@@ -1,40 +1,58 @@
enablePlugins(AndroidApp)
enablePlugins(AndroidGms)
android.useSupportVectors
name := "shadowsocks"
version := "4.1.4"
versionCode := Some(184)
version := "4.1.8"
versionCode := Some(188)
proguardOptions ++=
"-keep class com.github.shadowsocks.JniHelper { *; }" ::
"-dontwarn com.google.android.gms.internal.**" ::
"-dontwarn com.j256.ormlite.**" ::
"-dontwarn okhttp3.**" ::
"-dontwarn okio.**" ::
"-dontwarn org.xbill.**" ::
"-keep class com.github.shadowsocks.JniHelper { *; }" ::
Nil
val playServicesVersion = "10.2.1"
val playServicesVersion = "10.2.6"
resolvers += Resolver.jcenterRepo
libraryDependencies ++=
"com.futuremind.recyclerfastscroll" % "fastscroll" % "0.2.5" ::
"com.evernote" % "android-job" % "1.1.8" ::
"com.evernote" % "android-job" % "1.1.10" ::
"com.github.jorgecastilloprz" % "fabprogresscircle" % "1.01" ::
"com.google.android.gms" % "play-services-ads" % playServicesVersion ::
"com.google.android.gms" % "play-services-analytics" % playServicesVersion ::
"com.google.android.gms" % "play-services-gcm" % playServicesVersion ::
"com.google.firebase" % "firebase-config" % playServicesVersion ::
"com.j256.ormlite" % "ormlite-android" % "5.0" ::
"com.mikepenz" % "crossfader" % "1.5.0" ::
"com.mikepenz" % "fastadapter" % "2.5.0" ::
"com.mikepenz" % "iconics-core" % "2.8.2" ::
"com.mikepenz" % "materialdrawer" % "5.9.0" ::
"com.mikepenz" % "fastadapter" % "2.5.2" ::
"com.mikepenz" % "iconics-core" % "2.8.4" ::
"com.mikepenz" % "materialdrawer" % "5.9.1" ::
"com.mikepenz" % "materialize" % "1.0.1" ::
"com.squareup.okhttp3" % "okhttp" % "3.6.0" ::
"com.squareup.okhttp3" % "okhttp" % "3.8.0" ::
"com.twofortyfouram" % "android-plugin-api-for-locale" % "1.0.2" ::
"dnsjava" % "dnsjava" % "2.1.8" ::
"eu.chainfire" % "libsuperuser" % "1.0.0.201704021214" ::
"me.dm7.barcodescanner" % "zxing" % "1.9.3" ::
"net.glxn.qrgen" % "android" % "2.0" ::
Nil
packagingOptions := PackagingOptions(excludes =
"META-INF/maven/com.squareup.okio/okio/pom.properties" ::
"META-INF/maven/com.squareup.okio/okio/pom.xml" ::
"META-INF/maven/com.squareup.okhttp3/okhttp/pom.properties" ::
"META-INF/maven/com.squareup.okhttp3/okhttp/pom.xml" ::
Nil)
lazy val goClean = TaskKey[Unit]("go-clean", "Clean go build dependencies")
goClean := {
IO.delete(baseDirectory(base => base / "src/overture/.deps").value)
IO.delete(baseDirectory(base => base / "src/main/jni/overture").value)
}
lazy val goBuild = TaskKey[Unit]("go-build", "Build go and overture")
goBuild := {
Process(Seq("mobile/src/overture/make.bash", minSdkVersion.value)) ! streams.value.log match {
+50
View File
@@ -0,0 +1,50 @@
{
"project_info": {
"project_number": "261400168171",
"firebase_url": "https://admob-app-id-3330146721.firebaseio.com",
"project_id": "admob-app-id-3330146721",
"storage_bucket": "admob-app-id-3330146721.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:261400168171:android:dbdd6331c434162f",
"android_client_info": {
"package_name": "com.github.shadowsocks"
}
},
"oauth_client": [
{
"client_id": "261400168171-sfik8o3pj7e243583olorh7s5974vab1.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "com.github.shadowsocks",
"certificate_hash": "58a90f84cfe99d4280aec677c9a1292fae131677"
}
},
{
"client_id": "261400168171-g7aelv5bu012ojr7dod7lq09c9anjimh.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyCee3fAad7nb3YsxeUO9mqqHFfAvsSCbVs"
}
],
"services": {
"analytics_service": {
"status": 1
},
"appinvite_service": {
"status": 1,
"other_platform_oauth_client": []
},
"ads_service": {
"status": 2
}
}
}
],
"configuration_version": "1"
}
+9
View File
@@ -4,6 +4,7 @@
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.touchscreen"
android:required="false"/>
@@ -11,6 +12,8 @@
android:required="false"/>
<uses-feature android:name="android.software.leanback"
android:required="false"/>
<uses-feature android:name="android.hardware.camera"
android:required="false"/>
<uses-sdk
android:minSdkVersion="19"
@@ -75,6 +78,12 @@
android:excludeFromRecents="true"
android:launchMode="singleTask"/>
<activity
android:name=".ScannerActivity"
android:label="@string/add_profile_methods_scan_qr_code"
android:parentActivityName=".MainActivity"
android:excludeFromRecents="true"/>
<activity android:name=".TaskerActivity"
android:icon="@mipmap/ic_launcher">
<intent-filter>
+2 -2
View File
@@ -291,13 +291,13 @@ along with this program. If not, see <a href="http://www.gnu.org/licenses/">http
<ul>
<li>redsocks: <a href="https://github.com/shadowsocks/redsocks/blob/shadowsocks-android/README">APL 2.0</a></li>
<li>mbed TLS: <a href="https://github.com/ARMmbed/mbedtls/blob/development/LICENSE">APL 2.0</a></li>
<li>libevent: <a href="https://github.com/shadowsocks/shadowsocks-android/blob/master/src/main/jni/libevent/LICENSE">BSD</a></li>
<li>libevent: <a href="https://github.com/shadowsocks/libevent/blob/master/LICENSE">BSD</a></li>
<li>tun2socks: <a href="https://github.com/shadowsocks/badvpn/blob/shadowsocks-android/COPYING">BSD</a></li>
<li>pcre: <a href="https://android.googlesource.com/platform/external/pcre/+/master/dist2/LICENCE">BSD</a></li>
<li>libancillary: <a href="https://github.com/shadowsocks/libancillary/blob/shadowsocks-android/COPYING">BSD</a></li>
<li>shadowsocks-libev: <a href="https://github.com/shadowsocks/shadowsocks-libev/blob/master/LICENSE">GPLv3</a></li>
<li>overture: <a href="https://github.com/shawn1m/overture/blob/master/LICENSE">MIT</a></li>
<li>libev: <a href="https://github.com/shadowsocks/shadowsocks-libev/blob/master/libev/LICENSE">GPLv2</a></li>
<li>libev: <a href="https://github.com/shadowsocks/libev/blob/master/LICENSE">GPLv2</a></li>
<li>libsodium: <a href="https://github.com/jedisct1/libsodium/blob/master/LICENSE">ISC</a></li>
<li>libudns: <a href="https://github.com/shadowsocks/libudns/blob/master/COPYING.LGPL">LGPL</a></li>
</ul>
+2 -2
View File
@@ -257,7 +257,7 @@ SHADOWSOCKS_SOURCES := local.c \
LOCAL_MODULE := ss-local
LOCAL_SRC_FILES := $(addprefix shadowsocks-libev/src/, $(SHADOWSOCKS_SOURCES))
LOCAL_CFLAGS := -Wall -O2 -fno-strict-aliasing -DMODULE_LOCAL \
-DUSE_CRYPTO_MBEDTLS -DANDROID -DHAVE_CONFIG_H \
-DUSE_CRYPTO_MBEDTLS -DHAVE_CONFIG_H \
-DCONNECT_IN_PROGRESS=EINPROGRESS \
-I$(LOCAL_PATH)/include/shadowsocks-libev \
-I$(LOCAL_PATH)/include \
@@ -294,7 +294,7 @@ SHADOWSOCKS_SOURCES := tunnel.c \
LOCAL_MODULE := ss-tunnel
LOCAL_SRC_FILES := $(addprefix shadowsocks-libev/src/, $(SHADOWSOCKS_SOURCES))
LOCAL_CFLAGS := -Wall -O2 -fno-strict-aliasing -DMODULE_TUNNEL \
-DUSE_CRYPTO_MBEDTLS -DANDROID -DHAVE_CONFIG_H -DSSTUNNEL_JNI \
-DUSE_CRYPTO_MBEDTLS -DHAVE_CONFIG_H -DSSTUNNEL_JNI \
-DCONNECT_IN_PROGRESS=EINPROGRESS \
-I$(LOCAL_PATH)/libancillary \
-I$(LOCAL_PATH)/include \
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/toolbar_light_dark" />
<me.dm7.barcodescanner.zxing.ZXingScannerView android:id="@+id/scanner"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
Binary file not shown.
+2 -1
View File
@@ -91,6 +91,7 @@
<string name="add_profile_methods_scan_qr_code">"QR コードを読み取る"</string>
<string name="add_profile_methods_manual_settings">"手動設定"</string>
<string name="add_profile_scanner_not_installed">"Zxingに準拠したQRコードスキャンアプリをインストールして下さい"</string>
<string name="add_profile_scanner_permission_required">QRコードを読み取るにはカメラの使用権限が必要です。</string>
<plurals name="removed">
<item quantity="other">"削除済み"</item>
</plurals>
@@ -132,4 +133,4 @@
<string name="plugin_unknown">"不明なプラグイン"</string>
<string name="plugin_untrusted">"警告:このプラグインは信頼されていないソースからの可能性があります"</string>
<string name="profile_plugin">"プラグイン"</string>
</resources>
</resources>
+2 -2
View File
@@ -2,8 +2,7 @@
<resources>
<string name="quick_toggle">"켜기/끄기"</string>
<!-- global/misc category -->
<string name="misc_cat">"기타"</string>
<!-- misc -->
<string name="profile">"프로필"</string>
<string name="profile_summary">"다른 프로필로 전환하거나 새 프로필 추가"</string>
<string name="nat">"NAT 모드 (지원 중단)"</string>
@@ -45,4 +44,5 @@
<string name="tcp_fastopen_summary">"루트 권한이 필요합니다"</string>
<string name="tcp_fastopen_summary_unsupported">"지원하지 않는 버전의 커널입니다: %s &lt; 3.7.1"</string>
<string name="udp_dns">"DNS 포워딩"</string>
<string name="udp_dns_summary">"모든 DNS 요청을 외부로 포워딩 합니다"</string>
</resources>
+59 -23
View File
@@ -2,22 +2,28 @@
<resources>
<string name="quick_toggle">"Подключение"</string>
<!-- global/misc category -->
<string name="misc_cat">"Разное"</string>
<!-- misc -->
<string name="profile">"Профиль"</string>
<string name="profile_summary">"Переключить на другой профиль или добавить новые"</string>
<string name="nat">"Режим NAT (не рекомендуется)"</string>
<string name="nat_summary">"Использовать режим NAT вместо VPN. Требует ROOT прав."</string>
<string name="stat_summary">"Отправлено: \t\t\t\t\t%3$s\t↑\t%1$s/s
<string name="remote_dns">"Удалённый DNS"</string>
<string name="stat_summary">"Отправлено: \t%3$s\t↑\t%1$s/s
Получено: \t%4$s\t↓\t%2$s/s"</string>
<string name="stat_profiles">"
%1$s↑\t%2$s↓"</string>
<string name="traffic_summary">"%1$s/s↑\t%2$s/s↓"</string>
<string name="connection_test_pending">"Проверить подключение"</string>
<plurals name="bytes">
<item quantity="one">"байт"</item>
<item quantity="few">"байта"</item>
<item quantity="many">"байт"</item>
<item quantity="other">"байт"</item>
</plurals>
<string name="connection_test_pending">"Проверить соединение"</string>
<string name="connection_test_testing">"Проверка…"</string>
<string name="connection_test_available">"Успешно: %dms задержка"</string>
<string name="connection_test_error">"Сбой проверки интернет подключения: %s"</string>
<string name="connection_test_fail">"Интернет Недоступен"</string>
<string name="connection_test_available">"Успешно: задержка %d мс"</string>
<string name="connection_test_error">"Сбой проверки интернет-соединения: %s"</string>
<string name="connection_test_fail">"Интернет недоступен"</string>
<string name="connection_test_error_status_code">"Код ошибки: #%d"</string>
<!-- proxy category -->
@@ -30,7 +36,7 @@
<!-- feature category -->
<string name="ipv6">"IPv6 Маршрут"</string>
<string name="ipv6_summary">"Перенаправлять IPv6 траффик на удалённый сервер"</string>
<string name="ipv6_summary">"Перенаправлять трафик IPv6 на удалённый сервер"</string>
<string name="route_list">"Маршрут"</string>
<string name="route_entry_gfwlist">"Список GFW"</string>
<string name="proxied_apps">"Прокси для выбранных приложений"</string>
@@ -42,22 +48,23 @@
<string name="auto_connect_summary">"Запускать Shadowsocks при включении"</string>
<string name="tcp_fastopen_summary">"Переключение требует наличия ROOT прав"</string>
<string name="tcp_fastopen_summary_unsupported">"Неподдерживаемая версия ядра: %s &lt; 3.7.1"</string>
<string name="udp_dns">"Проброс DNS"</string>
<string name="udp_dns_summary">"Пробрасывать DNS пакеты на удалённый сервер"</string>
<string name="udp_dns">"Перенаправление DNS"</string>
<string name="udp_dns_summary">"Перенаправлять все DNS-запросы на удалённый сервер"</string>
<!-- notification category -->
<string name="forward_success">"Shadowsocks запущен."</string>
<string name="invalid_server">"Неправильное имя сервера"</string>
<string name="service_failed">"Ошибка при подключении к удалённому серверу"</string>
<string name="nat_deprecated">"ВНИМАНИЕ:режим NAT не работает в Android 5.0"</string>
<string name="nat_deprecated">"ВНИМАНИЕ: режим NAT не рекомендуется, начиная с Android 5.0"</string>
<string name="nat_no_root">"Режим NAT требует наличия ROOT прав"</string>
<string name="switch_to_vpn">"Переключить на режим VPN"</string>
<string name="stop">"Остановить"</string>
<string name="stopping">"Останавливается…"</string>
<string name="reboot_required">"Сбой запуска VPN сервиса. Требуется перезагрузка Вашего устройства."</string>
<string name="reboot_required">"Не удалось запустить службу VPN. Возможно, требуется перезагрузить ваше устройство."</string>
<!-- alert category -->
<string name="close">"Закрыть"</string>
<string name="profile_empty">"Пожалуйста, выберите профиль"</string>
<string name="proxy_empty">"Прокси/Пароль не должны быть пустыми"</string>
<string name="connect">"Подключить"</string>
<string name="recovering">"Сброс…"</string>
@@ -69,6 +76,7 @@
<string name="recovery">"Сброс"</string>
<string name="about">"О приложении"</string>
<string name="about_title">"Shadowsocks %s"</string>
<string name="edit">"Изменить"</string>
<string name="share">"Поделиться"</string>
<string name="add_profile">"Добавить Профиль"</string>
<string name="action_apply_all">"Применить настройки для всех профилей"</string>
@@ -78,19 +86,27 @@
<string name="action_export_err">"Сбой экспорта."</string>
<string name="action_import_msg">"Успешный импорт!"</string>
<string name="action_import_err">"Сбой импорта."</string>
<!-- profile -->
<string name="profile_config">"Настройка профиля"</string>
<string name="delete">"Удалить"</string>
<string name="delete_confirm_prompt">"Вы уверены, что хотите удалить этот профиль?"</string>
<string name="share_qr_nfc">"QR-код/NFC"</string>
<string name="add_profile_dialog">"Добавить этот Профиль Shadowsocks?"</string>
<string name="add_profile_methods_scan_qr_code">"Сканировать QR код"</string>
<string name="add_profile_methods_manual_settings">"Настройка вручную"</string>
<string name="add_profile_methods_scan_qr_code">"Сканировать QR-код"</string>
<string name="add_profile_methods_manual_settings">"Ручные настройки"</string>
<string name="add_profile_scanner_not_installed">"Пожалуйста, установите любое ZXing-совместимое приложение для сканирования QR-кодов."</string>
<string name="add_profile_scanner_permission_required">Разрешение камеры требуется для сканирования QR код.</string>
<plurals name="removed">
<item quantity="one">"Удалён"</item>
<item quantity="few">"%d элементы удалены"</item>
<item quantity="many">"%d элементы удалены"</item>
<item quantity="other">"%d элементы удалены"</item>
<item quantity="one">"Удалено"</item>
<item quantity="few">"Удалено %d элемента"</item>
<item quantity="many">"Удалено %d элементов"</item>
<item quantity="other">"Удалено %d элементов"</item>
</plurals>
<string name="undo">"Вернуть"</string>
<!-- tasker -->
<string name="toggle_service_state">"Запустить сервисStart the service"</string>
<string name="toggle_service_state">"Запустить службу"</string>
<string name="start_service_default">"Подключиться к текущему серверу"</string>
<string name="start_service">"Подключиться к %s"</string>
<string name="stop_service">"Переключить на %s"</string>
@@ -99,10 +115,30 @@
<!-- status -->
<string name="sent">"Отправлено:"</string>
<string name="received">"Получено:"</string>
<string name="connecting">"Соединение..."</string>
<string name="vpn_connected">"Подключено, нажмите для проверки соединения"</string>
<string name="nat_connected">"Подключено"</string>
<string name="not_connected">"Не подключено"</string>
<!-- acl -->
<string name="custom_rules">"Пользовательские правила"</string>
<string name="action_selection">"Выделение..."</string>
<string name="action_add_rule">"Добавить правило..."</string>
<string name="edit_rule">"Редактировать правило"</string>
<string name="route_entry_all">"Все"</string>
<string name="route_entry_bypass_lan">"Обход LAN"</string>
<string name="route_entry_bypass_chn">"Обходной Китай"</string>
<string name="route_entry_bypass_lan_chn">"Обход LAN и Китай"</string>
<string name="route_entry_bypass_lan">"Все, кроме LAN"</string>
<string name="route_entry_bypass_chn">"Все, кроме Китая"</string>
<string name="route_entry_bypass_lan_chn">"Все, кроме LAN и Китая"</string>
<string name="route_entry_chinalist">"Список Китай"</string>
<string name="proxied_apps_summary_v21">"Установить прокси для выбранных приложений"</string>
</resources>
<string name="acl_rule_templates_generic">"Подсеть/Регулярное выражение (PCRE) имени хоста"</string>
<string name="acl_rule_templates_domain">"Доменное имя и все его поддомены"</string>
<!-- plugin -->
<string name="plugin">"Плагин"</string>
<string name="plugin_configure">"Настроить..."</string>
<string name="plugin_disabled">"Отключён"</string>
<string name="plugin_unknown">"Неизвестный плагин %s"</string>
<string name="plugin_untrusted">"Предупреждение: этот плагин получен из недоверенного источника."</string>
<string name="profile_plugin">"Плагин: %s"</string>
</resources>
@@ -92,6 +92,7 @@
<string name="add_profile_methods_scan_qr_code">"扫描二维码"</string>
<string name="add_profile_methods_manual_settings">"手动设置"</string>
<string name="add_profile_scanner_not_installed">"请安装任意兼容 ZXing 的二维码扫描应用。"</string>
<string name="add_profile_scanner_permission_required">扫描二维码需要相机权限。</string>
<plurals name="removed">
<item quantity="other">"已删除 %d 项"</item>
</plurals>
@@ -133,4 +134,4 @@
<string name="plugin_unknown">"未知插件 %s"</string>
<string name="plugin_untrusted">"警告:该插件似乎并非来自已知的可信源。"</string>
<string name="profile_plugin">"插件:%s"</string>
</resources>
</resources>
+11 -3
View File
@@ -2,8 +2,7 @@
<resources>
<string name="quick_toggle">"切換"</string>
<!-- global/misc category -->
<string name="misc_cat">"其他"</string>
<!-- misc -->
<string name="profile">"設定檔"</string>
<string name="profile_summary">"切換至其他設定檔或新增新設定檔"</string>
<string name="nat">"NAT 模式 (已過時)"</string>
@@ -91,6 +90,7 @@
<string name="add_profile_methods_scan_qr_code">"掃描 QR 碼"</string>
<string name="add_profile_methods_manual_settings">"手動設定"</string>
<string name="add_profile_scanner_not_installed">"請安裝任何相容 ZXing 的 QR 碼掃描應用程式。"</string>
<string name="add_profile_scanner_permission_required">掃描 QR 碼需要相機權限。</string>
<plurals name="removed">
<item quantity="other">"已移除 %d 項"</item>
</plurals>
@@ -124,4 +124,12 @@
<string name="proxied_apps_summary_v21">"為已選擇的應用程式設定 Proxy"</string>
<string name="acl_rule_templates_generic">"子網路/主機名稱 PCRE 模式"</string>
<string name="acl_rule_templates_domain">"網域及其所有子網域"</string>
</resources>
<!-- plugin -->
<string name="plugin">"插件"</string>
<string name="plugin_configure">"配置..."</string>
<string name="plugin_disabled">"未啟用"</string>
<string name="plugin_unknown">"未知插件 %s"</string>
<string name="plugin_untrusted">"警告:該插件似乎不是來自一個已知的可信任源。"</string>
<string name="profile_plugin">"插件: %s"</string>
</resources>
+1
View File
@@ -104,6 +104,7 @@
<string name="add_profile_methods_scan_qr_code">Scan QR code</string>
<string name="add_profile_methods_manual_settings">Manual Settings</string>
<string name="add_profile_scanner_not_installed">Please install any ZXing-compliant QR code scanning app.</string>
<string name="add_profile_scanner_permission_required">Camera permission is required for scanning QR code.</string>
<plurals name="removed">
<item quantity="one">Removed</item>
<item quantity="other">%d items removed</item>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<defaultsMap>
<entry>
<key>proxy_url</key>
<value>https://www.socks123.pw/get.php</value>
</entry>
</defaultsMap>
@@ -21,7 +21,6 @@
package com.github.shadowsocks
import java.io.{File, IOException}
import java.net.InetAddress
import java.util
import java.util.concurrent.TimeUnit
import java.util.{Timer, TimerTask}
@@ -127,12 +126,8 @@ trait BaseService extends Service {
def connect() {
profile.name = profile.getName // save original name before it's (possibly) overwritten by IP addresses
if (profile.host == "198.199.101.152") {
val holder = app.containerHolder
val container = holder.getContainer
val url = container.getString("proxy_url")
val sig = Utils.getSignature(this)
if (profile.host == "198.199.101.152") {
val client = new OkHttpClient.Builder()
.dns(hostname => Utils.resolve(hostname, enableIPv6 = false) match {
case Some(ip) => util.Arrays.asList(InetAddress.getByName(ip))
@@ -143,10 +138,10 @@ trait BaseService extends Service {
.readTimeout(30, TimeUnit.SECONDS)
.build()
val requestBody = new FormBody.Builder()
.add("sig", sig)
.add("sig", Utils.getSignature(this))
.build()
val request = new Request.Builder()
.url(url)
.url(app.remoteConfig.getString("proxy_url"))
.post(requestBody)
.build()
@@ -277,7 +272,6 @@ trait BaseService extends Service {
override def onCreate() {
super.onCreate()
app.refreshContainerHolder()
app.updateAssets()
}
@@ -302,23 +296,12 @@ trait BaseService extends Service {
}
}
def getBlackList: String = {
val default = getString(R.string.black_list)
try {
val container = app.containerHolder.getContainer
val update = container.getString("black_list_lite")
val list = if (update == null || update.isEmpty) default else update
"exclude = " + list + ";"
} catch {
case _: Exception => "exclude = " + default + ";"
}
}
protected def buildPluginCommandLine(): ArrayBuffer[String] = {
val result = ArrayBuffer(pluginPath)
if (TcpFastOpen.sendEnabled) result += "--fast-open"
result
}
protected final def buildShadowsocksConfig(file: String): String = {
val config = new JSONObject()
.put("server", profile.host)
@@ -332,16 +315,9 @@ trait BaseService extends Service {
file
}
private final def buildRemoteDns(remoteDns: String): String = {
val addr = InetAddress.getByName(remoteDns)
if (addr.isInstanceOf[Inet6Address])
return "[" + remoteDns + "]"
remoteDns
}
protected final def buildOvertureConfig(file: String): String = {
val config = new JSONObject()
.put("BindAddress", ":" + (profile.localPort + 53))
.put("BindAddress", "127.0.0.1:" + (profile.localPort + 53))
.put("RedirectIPv6Record", true)
.put("DomainBase64Decode", true)
.put("HostsFile", "hosts")
@@ -350,7 +326,10 @@ trait BaseService extends Service {
def makeDns(name: String, address: String, edns: Boolean = true) = {
val dns = new JSONObject()
.put("Name", name)
.put("Address", address + ":53")
.put("Address", (Utils.parseNumericAddress(address) match {
case _: Inet6Address => '[' + address + ']'
case _ => address
}) + ":53")
.put("Timeout", 6)
.put("EDNSClientSubnet", new JSONObject().put("Policy", "disable"))
if (edns) dns
@@ -359,24 +338,25 @@ trait BaseService extends Service {
else dns.put("Protocol", "udp")
dns
}
val remoteDns = new JSONArray(profile.remoteDns.split(",").zipWithIndex.map {
case (dns, i) => makeDns("UserDef-" + i, dns.trim)
})
profile.route match {
case Acl.BYPASS_CHN | Acl.BYPASS_LAN_CHN | Acl.GFWLIST | Acl.CUSTOM_RULES => config
.put("PrimaryDNS", new JSONArray(Array(
makeDns("Primary-1", "119.29.29.29", edns = false),
makeDns("Primary-2", "114.114.114.114", edns = false)
)))
.put("AlternativeDNS", new JSONArray().put(makeDns("Alternative",
buildRemoteDns(profile.remoteDns.trim))))
.put("AlternativeDNS", remoteDns)
.put("IPNetworkFile", "china_ip_list.txt")
.put("DomainFile", "gfwlist.txt")
case Acl.CHINALIST => config
.put("PrimaryDNS", new JSONArray().put(makeDns("Primary", "119.29.29.29")))
.put("AlternativeDNS", new JSONArray().put(makeDns("Alternative",
buildRemoteDns(profile.remoteDns.trim))))
.put("AlternativeDNS", remoteDns)
case _ => config
.put("PrimaryDNS", new JSONArray().put(makeDns("Primary",
buildRemoteDns(profile.remoteDns.trim))))
.put("AlternativeDNS", new JSONArray().put(makeDns("Alternative", "208.67.222.222")))
.put("PrimaryDNS", remoteDns)
// no need to setup AlternativeDNS in Acl.ALL/BYPASS_LAN mode
.put("OnlyPrimaryDNS", true)
}
IOUtils.writeString(new File(getFilesDir, file), config.toString)
file
@@ -33,9 +33,9 @@ import com.github.shadowsocks.ShadowsocksApplication.app
import scala.collection.JavaConversions._
import scala.collection.immutable.Stream
class StreamLogger(is: InputStream, tag: String) extends Thread {
class StreamLogger(is: InputStream, tag: String, logger: (String, String) => Int) extends Thread {
override def run(): Unit = autoClose(new BufferedReader(new InputStreamReader(is)))(br =>
try Stream.continually(br.readLine()).takeWhile(_ != null).foreach(Log.i(tag, _)) catch {
try Stream.continually(br.readLine()).takeWhile(_ != null).foreach(logger(tag, _)) catch {
case _: IOException =>
})
}
@@ -68,8 +68,8 @@ class GuardedProcess(cmd: String*) {
.directory(app.getFilesDir)
.start()
val is = process.getInputStream
new StreamLogger(is, TAG).start()
new StreamLogger(process.getInputStream(), TAG, Log.i).start()
new StreamLogger(process.getErrorStream(), TAG, Log.e).start()
if (callback == null) callback = onRestartCallback else callback()
@@ -390,7 +390,7 @@ class MainActivity extends Activity with ServiceBoundContext with Drawer.OnDrawe
protected override def onResume() {
super.onResume()
app.refreshContainerHolder()
app.remoteConfig.fetch()
state match {
case State.STOPPING | State.CONNECTING =>
case _ => hideCircle()
@@ -352,21 +352,16 @@ final class ProfilesFragment extends ToolbarFragment with Toolbar.OnMenuItemClic
def onMenuItemClick(item: MenuItem): Boolean = item.getItemId match {
case R.id.action_scan_qr_code =>
def installScanner() = {
Toast.makeText(getActivity, R.string.add_profile_scanner_not_installed, Toast.LENGTH_LONG).show()
try startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=tw.com.quickmark"))) catch {
case exc: ActivityNotFoundException => exc.printStackTrace()
}
}
try startActivityForResult(new Intent("com.google.zxing.client.android.SCAN")
.addCategory(Intent.CATEGORY_DEFAULT)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_DOCUMENT),
REQUEST_SCAN_QR_CODE) catch {
case _: ActivityNotFoundException => installScanner()
case _: ActivityNotFoundException =>
startActivity(new Intent(getActivity, classOf[ScannerActivity]))
case e: SecurityException =>
e.printStackTrace()
app.track(e)
installScanner()
startActivity(new Intent(getActivity, classOf[ScannerActivity]))
}
true
case R.id.action_import =>
@@ -0,0 +1,105 @@
/*******************************************************************************/
/* */
/* Copyright (C) 2016 by Max Lv <max.c.lv@gmail.com> */
/* Copyright (C) 2016 by Mygod Studio <contact-shadowsocks-android@mygod.be> */
/* */
/* This program is free software: you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation, either version 3 of the License, or */
/* (at your option) any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*******************************************************************************/
package com.github.shadowsocks
import android.app.{Activity, TaskStackBuilder}
import android.content.Intent
import android.content.pm.{PackageManager, ShortcutManager}
import android.os.{Build, Bundle}
import android.support.v4.app.ActivityCompat
import android.support.v4.content.ContextCompat
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar
import android.text.TextUtils
import android.widget.Toast
import com.google.zxing.Result
import com.github.shadowsocks.ShadowsocksApplication.app
import com.github.shadowsocks.utils.Parser
import me.dm7.barcodescanner.zxing.ZXingScannerView
object ScannerActivity {
private final val MY_PERMISSIONS_REQUEST_CAMERA = 1
}
class ScannerActivity extends AppCompatActivity with ZXingScannerView.ResultHandler {
import ScannerActivity._
private var scannerView: ZXingScannerView = _
override def onRequestPermissionsResult(requestCode: Int, permissions: Array[String],
grantResults: Array[Int]) {
if (requestCode == MY_PERMISSIONS_REQUEST_CAMERA) {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults(0) == PackageManager.PERMISSION_GRANTED) {
scannerView.setResultHandler(this)
scannerView.startCamera()
} else {
Toast.makeText(this, R.string.add_profile_scanner_permission_required, Toast.LENGTH_SHORT).show()
finish()
}
}
}
def navigateUp() {
val intent = getParentActivityIntent
if (shouldUpRecreateTask(intent) || isTaskRoot)
TaskStackBuilder.create(this).addNextIntentWithParentStack(intent).startActivities()
else finish()
}
override def onCreate(state: Bundle) {
super.onCreate(state)
setContentView(R.layout.layout_scanner)
val toolbar = findViewById(R.id.toolbar).asInstanceOf[Toolbar]
toolbar.setTitle(getTitle)
toolbar.setNavigationIcon(R.drawable.abc_ic_ab_back_material)
toolbar.setNavigationOnClickListener(_ => navigateUp())
scannerView = findViewById(R.id.scanner).asInstanceOf[ZXingScannerView]
if (Build.VERSION.SDK_INT >= 25) getSystemService(classOf[ShortcutManager]).reportShortcutUsed("scan")
}
override def onResume() {
super.onResume()
val permissionCheck = ContextCompat.checkSelfPermission(this,
android.Manifest.permission.CAMERA)
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
scannerView.setResultHandler(this) // Register ourselves as a handler for scan results.
scannerView.startCamera() // Start camera on resume
} else {
ActivityCompat.requestPermissions(this,
Array(android.Manifest.permission.CAMERA), MY_PERMISSIONS_REQUEST_CAMERA)
}
}
override def onPause() {
super.onPause()
scannerView.stopCamera() // Stop camera on pause
}
override def handleResult(rawResult: Result) = {
val uri = rawResult.getText
if (!TextUtils.isEmpty(uri))
Parser.findAll(uri).foreach(app.profileManager.createProfile)
navigateUp()
}
}
@@ -21,9 +21,7 @@
package com.github.shadowsocks
import java.io.{File, FileOutputStream, IOException}
import java.util
import java.util.Locale
import java.util.concurrent.TimeUnit
import android.annotation.SuppressLint
import android.app.Application
@@ -39,8 +37,8 @@ import com.github.shadowsocks.database.{DBHelper, Profile, ProfileManager}
import com.github.shadowsocks.utils.CloseUtils._
import com.github.shadowsocks.utils._
import com.google.android.gms.analytics.{GoogleAnalytics, HitBuilders, StandardExceptionParser, Tracker}
import com.google.android.gms.common.api.ResultCallback
import com.google.android.gms.tagmanager.{ContainerHolder, TagManager}
import com.google.firebase.FirebaseApp
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import com.j256.ormlite.logger.LocalLog
import eu.chainfire.libsuperuser.Shell
@@ -61,8 +59,7 @@ object ShadowsocksApplication {
class ShadowsocksApplication extends Application {
import ShadowsocksApplication._
final val SIG_FUNC = "getSignature"
var containerHolder: ContainerHolder = _
lazy val remoteConfig = FirebaseRemoteConfig.getInstance()
lazy val tracker: Tracker = GoogleAnalytics.getInstance(this).newTracker(R.xml.tracker)
lazy val settings: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
lazy val editor: SharedPreferences.Editor = settings.edit
@@ -149,35 +146,16 @@ class ShadowsocksApplication extends Application {
if (!BuildConfig.DEBUG) java.lang.System.setProperty(LocalLog.LOCAL_LOG_LEVEL_PROPERTY, "ERROR")
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
checkChineseLocale(getResources.getConfiguration)
val tm = TagManager.getInstance(this)
val pending = tm.loadContainerPreferNonDefault("GTM-NT8WS8", R.raw.gtm_default_container)
val callback = new ResultCallback[ContainerHolder] {
override def onResult(holder: ContainerHolder) {
if (!holder.getStatus.isSuccess) {
return
}
containerHolder = holder
val container = holder.getContainer
container.registerFunctionCallMacroCallback(SIG_FUNC,
(functionName: String, parameters: util.Map[String, AnyRef]) => {
if (functionName == SIG_FUNC) {
Utils.getSignature(getApplicationContext)
}
null
})
}
}
pending.setResultCallback(callback, 2, TimeUnit.SECONDS)
FirebaseApp.initializeApp(this)
remoteConfig.setDefaults(R.xml.default_configs)
remoteConfig.fetch().addOnCompleteListener(task => if (task.isSuccessful) remoteConfig.activateFetched())
JobManager.create(this).addJobCreator(DonaldTrump)
TcpFastOpen.enabled(settings.getBoolean(Key.tfo, TcpFastOpen.sendEnabled))
}
def refreshContainerHolder() {
val holder = app.containerHolder
if (holder != null) holder.refresh()
}
def crashRecovery() {
val cmd = new ArrayBuffer[String]()
@@ -74,7 +74,7 @@ class ShadowsocksNatService extends BaseService {
"-t", "10",
"-b", "127.0.0.1",
"-l", (profile.localPort + 63).toString,
"-L", profile.remoteDns.trim + ":53",
"-L", profile.remoteDns.split(",").head.trim + ":53",
"-c", buildShadowsocksConfig("ss-tunnel-nat.conf"))
if (profile.udpdns) cmd.append("-u")
@@ -22,8 +22,6 @@ package com.github.shadowsocks
import java.io.File
import java.util.Locale
import java.net.InetAddress
import java.net.Inet6Address
import android.content._
import android.content.pm.PackageManager.NameNotFoundException
@@ -145,7 +143,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
/** Called when the activity is first created. */
def handleConnection() {
startShadowsocksDaemon()
if (!profile.udpdns) {
@@ -216,18 +214,17 @@ class ShadowsocksVpnService extends VpnService with BaseService {
}
}
if (profile.route == Acl.ALL || profile.route == Acl.BYPASS_CHN) {
if (profile.route == Acl.ALL
|| profile.route == Acl.BYPASS_CHN
|| profile.route == Acl.CUSTOM_RULES) {
builder.addRoute("0.0.0.0", 0)
} else {
getResources.getStringArray(R.array.bypass_private_route).foreach(cidr => {
val subnet = Subnet.fromString(cidr)
builder.addRoute(subnet.address.getHostAddress, subnet.prefixSize)
})
val addr = InetAddress.getByName(profile.remoteDns.trim)
if (addr.isInstanceOf[Inet6Address])
builder.addRoute(addr, 128)
else if (addr.isInstanceOf[InetAddress])
builder.addRoute(addr, 32)
profile.remoteDns.split(",").map(dns => Utils.parseNumericAddress(dns.trim)).foreach(dns =>
builder.addRoute(dns, dns.getAddress.length << 3))
}
conn = builder.establish()
@@ -250,7 +247,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
cmd += "--enable-udprelay"
if (!profile.udpdns)
cmd += ("--dnsgw", "%s:%d".formatLocal(Locale.ENGLISH, PRIVATE_VLAN.formatLocal(Locale.ENGLISH, "1"),
cmd += ("--dnsgw", "%s:%d".formatLocal(Locale.ENGLISH, "127.0.0.1",
profile.localPort + 53))
tun2socksProcess = new GuardedProcess(cmd: _*).start(() => sendFd(fd))
@@ -34,6 +34,7 @@ import scala.io.Source
*/
object AclSyncJob {
final val TAG = "AclSyncJob"
final val MAX_RESCHEDULE = 3
def schedule(route: String): Int = new JobRequest.Builder(AclSyncJob.TAG + ':' + route)
.setExecutionWindow(TimeUnit.SECONDS.toMillis(10), TimeUnit.DAYS.toMillis(28))
@@ -54,7 +55,7 @@ class AclSyncJob(route: String) extends Job {
} catch {
case e: IOException =>
e.printStackTrace()
Result.RESCHEDULE
if (params.getFailureCount < AclSyncJob.MAX_RESCHEDULE) Result.RESCHEDULE else Result.FAILURE
case e: Exception => // unknown failures, probably shouldn't retry
e.printStackTrace()
Result.FAILURE
@@ -80,7 +80,9 @@ object Utils {
def resolve(host: String, addrType: Int): Option[String] = {
try {
val lookup = new Lookup(host, addrType)
val resolver = new SimpleResolver("114.114.114.114")
val resolver = new SimpleResolver("208.67.220.220")
resolver.setTCP(true)
resolver.setPort(443)
resolver.setTimeout(5)
lookup.setResolver(resolver)
val result = lookup.run()
+4 -4
View File
@@ -4,7 +4,7 @@ function try () {
"$@" || exit -1
}
[ -z "$ANDROID_NDK_HOME" ] && ANDROID_NDK_HOME=~/android-ndk-r12b
[ -z "$ANDROID_NDK_HOME" ] && ANDROID_NDK_HOME=$ANDROID_HOME/ndk-bundle
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
MIN_API=$1
@@ -15,13 +15,13 @@ ANDROID_ARM_TOOLCHAIN=$DEPS/android-toolchain-${MIN_API}-arm
ANDROID_ARM64_TOOLCHAIN=$DEPS/android-toolchain-21-arm64
ANDROID_X86_TOOLCHAIN=$DEPS/android-toolchain-${MIN_API}-x86
ANDROID_ARM_CC=$ANDROID_ARM_TOOLCHAIN/bin/arm-linux-androideabi-gcc
ANDROID_ARM_CC=$ANDROID_ARM_TOOLCHAIN/bin/arm-linux-androideabi-clang
ANDROID_ARM_STRIP=$ANDROID_ARM_TOOLCHAIN/bin/arm-linux-androideabi-strip
ANDROID_ARM64_CC=$ANDROID_ARM64_TOOLCHAIN/bin/aarch64-linux-android-gcc
ANDROID_ARM64_CC=$ANDROID_ARM64_TOOLCHAIN/bin/aarch64-linux-android-clang
ANDROID_ARM64_STRIP=$ANDROID_ARM64_TOOLCHAIN/bin/aarch64-linux-android-strip
ANDROID_X86_CC=$ANDROID_X86_TOOLCHAIN/bin/i686-linux-android-gcc
ANDROID_X86_CC=$ANDROID_X86_TOOLCHAIN/bin/i686-linux-android-clang
ANDROID_X86_STRIP=$ANDROID_X86_TOOLCHAIN/bin/i686-linux-android-strip
try mkdir -p $DEPS $TARGET/armeabi-v7a $TARGET/x86 $TARGET/arm64-v8a
@@ -6,4 +6,10 @@
<!-- feature category -->
<string name="feature_cat">"Дополнительные Настройки"</string>
<!-- alert category -->
<string name="yes">"Да"</string>
<string name="no">"Нет"</string>
<string name="unsaved_changes_prompt">"Изменения не сохранены. Сохранить?"</string>
<string name="apply">"Применить"</string>
</resources>
+2
View File
@@ -7,3 +7,5 @@ addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.8.2")
addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "1.1")
addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.0") // fot sbt-0.13.5 or higher
addSbtPlugin("org.scala-android" % "sbt-android-gms" % "0.4")