diff --git a/README.md b/README.md index e56eded8..3bcf2be2 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ## Shadowsocks for Android [![Build Status](https://api.travis-ci.org/shadowsocks/shadowsocks-android.svg)](https://travis-ci.org/shadowsocks/shadowsocks-android) -[![API](https://img.shields.io/badge/API-19%2B-brightgreen.svg?style=flat)](https://android-arsenal.com/api?level=19) +[![API](https://img.shields.io/badge/API-21%2B-brightgreen.svg?style=flat)](https://android-arsenal.com/api?level=21) [![Releases](https://img.shields.io/github/downloads/shadowsocks/shadowsocks-android/total.svg)](https://github.com/shadowsocks/shadowsocks-android/releases) [![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) diff --git a/build.gradle b/build.gradle index 92e6c03e..039d7e95 100644 --- a/build.gradle +++ b/build.gradle @@ -2,8 +2,8 @@ buildscript { ext { - kotlinVersion = '1.2.10' - minSdkVersion = 19 + kotlinVersion = '1.2.20' + minSdkVersion = 21 sdkVersion = 27 buildToolsVersion = '27.0.3' supportLibraryVersion = '27.0.2' diff --git a/core/src/main/java/com/github/shadowsocks/JniHelper.java b/core/src/main/java/com/github/shadowsocks/JniHelper.java index ff111a65..d4167a67 100755 --- a/core/src/main/java/com/github/shadowsocks/JniHelper.java +++ b/core/src/main/java/com/github/shadowsocks/JniHelper.java @@ -43,8 +43,6 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.system.ErrnoException; -import java.net.InetAddress; - public class JniHelper { static { System.loadLibrary("jni-helper"); @@ -54,8 +52,7 @@ public class JniHelper { public static void sigtermCompat(@NonNull Process process) throws Exception { if (Build.VERSION.SDK_INT >= 24) throw new UnsupportedOperationException("Never call this method in OpenJDK!"); int errno = sigterm(process); - if (errno != 0) throw Build.VERSION.SDK_INT >= 21 - ? new ErrnoException("kill", errno) : new Exception("kill failed: " + errno); + if (errno != 0) throw new ErrnoException("kill", errno); } @Deprecated // only implemented for before API 24 diff --git a/core/src/overture/make.bash b/core/src/overture/make.bash index a857f2c5..0aadf24e 100755 --- a/core/src/overture/make.bash +++ b/core/src/overture/make.bash @@ -12,7 +12,7 @@ TARGET=$DIR/bin DEPS=$DIR/.deps ANDROID_ARM_TOOLCHAIN=$DEPS/android-toolchain-${MIN_API}-arm -ANDROID_ARM64_TOOLCHAIN=$DEPS/android-toolchain-21-arm64 +ANDROID_ARM64_TOOLCHAIN=$DEPS/android-toolchain-${MIN_API}-arm64 ANDROID_X86_TOOLCHAIN=$DEPS/android-toolchain-${MIN_API}-x86 ANDROID_ARM_CC=$ANDROID_ARM_TOOLCHAIN/bin/arm-linux-androideabi-clang @@ -35,7 +35,7 @@ fi if [ ! -f "$ANDROID_ARM64_CC" ]; then echo "Make standalone toolchain for ARM64 arch" $ANDROID_NDK_HOME/build/tools/make_standalone_toolchain.py --arch arm64 \ - --api 21 --install-dir $ANDROID_ARM64_TOOLCHAIN + --api $MIN_API --install-dir $ANDROID_ARM64_TOOLCHAIN fi if [ ! -f "$ANDROID_X86_CC" ]; then diff --git a/core/src/overture/make.bat b/core/src/overture/make.bat index 1dae4616..065de4f8 100644 --- a/core/src/overture/make.bat +++ b/core/src/overture/make.bat @@ -11,7 +11,7 @@ SET TARGET=%DIR%\bin SET DEPS=%DIR%\.deps SET ANDROID_ARM_TOOLCHAIN=%DEPS%\android-toolchain-%MIN_API%-arm -SET ANDROID_ARM64_TOOLCHAIN=%DEPS%\android-toolchain-21-arm64 +SET ANDROID_ARM64_TOOLCHAIN=%DEPS%\android-toolchain-%MIN_API%-arm64 SET ANDROID_X86_TOOLCHAIN=%DEPS%\android-toolchain-%MIN_API%-x86 SET ANDROID_ARM_CC=%ANDROID_ARM_TOOLCHAIN%\bin\arm-linux-androideabi-clang @@ -37,7 +37,7 @@ IF NOT EXIST %ANDROID_ARM_CC% ( IF NOT EXIST %ANDROID_ARM64_CC% ( ECHO "Make standalone toolchain for ARM64 arch" %ANDROID_NDK_HOME%\build\tools\make_standalone_toolchain.py --arch arm64 ^ - --api 21 --install-dir %ANDROID_ARM64_TOOLCHAIN% + --api %MIN_API% --install-dir %ANDROID_ARM64_TOOLCHAIN% ) IF NOT EXIST %ANDROID_X86_CC% ( diff --git a/mobile/build.gradle b/mobile/build.gradle index 51f22d6d..41add3a3 100644 --- a/mobile/build.gradle +++ b/mobile/build.gradle @@ -24,7 +24,6 @@ android { versionName "4.4.5" testApplicationId "com.github.shadowsocks.test" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - vectorDrawables.useSupportLibrary true resConfigs "fa", "fr", "ja", "ko", "ru", "zh-rCN", "zh-rTW" } buildTypes { @@ -48,17 +47,13 @@ dependencies { implementation "com.android.support:design:$supportLibraryVersion" implementation "com.android.support:gridlayout-v7:$supportLibraryVersion" implementation 'com.futuremind.recyclerfastscroll:fastscroll:0.2.5' - implementation 'com.evernote:android-job:1.2.1' + implementation 'com.evernote:android-job:1.2.2' implementation "com.google.android.gms:play-services-ads:$playServicesVersion" implementation "com.google.android.gms:play-services-analytics:$playServicesVersion" - implementation "com.google.android.gms:play-services-gcm:$playServicesVersion" implementation "com.google.firebase:firebase-config:$playServicesVersion" implementation 'com.j256.ormlite:ormlite-android:5.0' implementation 'com.mikepenz:crossfader:1.5.1' - implementation 'com.mikepenz:fastadapter:3.0.4' - implementation 'com.mikepenz:iconics-core:3.0.0' implementation 'com.mikepenz:materialdrawer:6.0.2' - implementation 'com.mikepenz:materialize:1.1.2' implementation 'com.squareup.okhttp3:okhttp:3.9.1' implementation "com.takisoft.fix:preference-v7-simplemenu:$takisoftFixVersion" implementation 'com.twofortyfouram:android-plugin-api-for-locale:1.0.2' diff --git a/mobile/src/main/AndroidManifest.xml b/mobile/src/main/AndroidManifest.xml index a552d5b1..fc8517ce 100644 --- a/mobile/src/main/AndroidManifest.xml +++ b/mobile/src/main/AndroidManifest.xml @@ -171,9 +171,11 @@ - + diff --git a/mobile/src/main/java/com/github/shadowsocks/ProfileConfigFragment.kt b/mobile/src/main/java/com/github/shadowsocks/ProfileConfigFragment.kt index ea511abe..98817951 100644 --- a/mobile/src/main/java/com/github/shadowsocks/ProfileConfigFragment.kt +++ b/mobile/src/main/java/com/github/shadowsocks/ProfileConfigFragment.kt @@ -80,13 +80,11 @@ class ProfileConfigFragment : PreferenceFragmentCompatDividers(), Toolbar.OnMenu val serviceMode = DataStore.serviceMode findPreference(Key.remoteDns).isEnabled = serviceMode != Key.modeProxy isProxyApps = findPreference(Key.proxyApps) as SwitchPreference - if (Build.VERSION.SDK_INT < 21) isProxyApps.parent!!.removePreference(isProxyApps) else { - isProxyApps.isEnabled = serviceMode == Key.modeVpn - isProxyApps.setOnPreferenceClickListener { - startActivity(Intent(activity, AppManager::class.java)) - isProxyApps.isChecked = true - false - } + isProxyApps.isEnabled = serviceMode == Key.modeVpn + isProxyApps.setOnPreferenceClickListener { + startActivity(Intent(activity, AppManager::class.java)) + isProxyApps.isChecked = true + false } findPreference(Key.udpdns).isEnabled = serviceMode != Key.modeProxy plugin = findPreference(Key.plugin) as IconListPreference diff --git a/mobile/src/main/java/com/github/shadowsocks/bg/Dns.kt b/mobile/src/main/java/com/github/shadowsocks/bg/Dns.kt index 05ab6bc9..56d6840d 100644 --- a/mobile/src/main/java/com/github/shadowsocks/bg/Dns.kt +++ b/mobile/src/main/java/com/github/shadowsocks/bg/Dns.kt @@ -20,49 +20,19 @@ package com.github.shadowsocks.bg -import android.content.Context -import android.net.ConnectivityManager -import android.net.LinkProperties -import android.os.Build import android.util.Log import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.BuildConfig -import okhttp3.Dns as Okdns import org.xbill.DNS.* import java.net.Inet6Address import java.net.InetAddress import java.net.NetworkInterface import java.net.UnknownHostException -import java.util.* +import okhttp3.Dns as Okdns object Dns { private const val TAG = "Dns" - @Throws(Exception::class) - fun getDnsResolver(context: Context): String { - val dnsResolvers = getDnsResolvers(context) - if (dnsResolvers.isEmpty()) throw Exception("Couldn't find an active DNS resolver") - val dnsResolver = dnsResolvers.iterator().next().toString() - if (dnsResolver.startsWith("/")) return dnsResolver.substring(1) - return dnsResolver - } - - @Throws(Exception::class) - private fun getDnsResolvers(context: Context): Collection { - val addresses = ArrayList() - val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager - val classLinkProperties = Class.forName("android.net.LinkProperties") - val getActiveLinkPropertiesMethod = ConnectivityManager::class.java.getMethod("getActiveLinkProperties") - val linkProperties = getActiveLinkPropertiesMethod.invoke(connectivityManager) - if (linkProperties != null) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - val dnses = classLinkProperties.getMethod("getDnses").invoke(linkProperties) as Collection<*> - dnses.mapTo(addresses) { it as InetAddress } - } else addresses.addAll((linkProperties as LinkProperties).dnsServers) - } - return addresses - } - private val hasIPv6Support get() = try { val result = NetworkInterface.getNetworkInterfaces().asSequence().flatMap { it.inetAddresses.asSequence() } .count { it is Inet6Address && !it.isLoopbackAddress && !it.isLinkLocalAddress } > 0 diff --git a/mobile/src/main/java/com/github/shadowsocks/bg/ServiceNotification.kt b/mobile/src/main/java/com/github/shadowsocks/bg/ServiceNotification.kt index e4974a21..cd16d74a 100644 --- a/mobile/src/main/java/com/github/shadowsocks/bg/ServiceNotification.kt +++ b/mobile/src/main/java/com/github/shadowsocks/bg/ServiceNotification.kt @@ -40,8 +40,7 @@ import java.util.* /** * Android < 8 VPN: always invisible because of VPN notification/icon - * Android 4.x other: always visible - * Android 5-7 other: only invisible in (possibly unsecure) lockscreen + * Android < 8 other: only invisible in (possibly unsecure) lockscreen * Android 8+: always visible due to system limitations * (user can choose to hide the notification in secure lockscreen or anywhere) */ @@ -85,24 +84,22 @@ class ServiceNotification(private val service: BaseService.Interface, profileNam if (Build.VERSION.SDK_INT < 24) builder.addAction(R.drawable.ic_navigation_close, service.getString(R.string.stop), PendingIntent.getBroadcast(service, 0, Intent(Action.CLOSE), 0)) val power = service.getSystemService(Context.POWER_SERVICE) as PowerManager - update(if (if (Build.VERSION.SDK_INT >= 20) power.isInteractive else @Suppress("DEPRECATION") power.isScreenOn) - Intent.ACTION_SCREEN_ON else Intent.ACTION_SCREEN_OFF, true) + update(if (power.isInteractive) Intent.ACTION_SCREEN_ON else Intent.ACTION_SCREEN_OFF, true) val screenFilter = IntentFilter() screenFilter.addAction(Intent.ACTION_SCREEN_ON) screenFilter.addAction(Intent.ACTION_SCREEN_OFF) - if (visible && Build.VERSION.SDK_INT in 21 until 26) screenFilter.addAction(Intent.ACTION_USER_PRESENT) + if (visible && Build.VERSION.SDK_INT < 26) screenFilter.addAction(Intent.ACTION_USER_PRESENT) service.registerReceiver(lockReceiver, screenFilter) } private fun update(action: String, forceShow: Boolean = false) { if (forceShow || service.data.state == BaseService.CONNECTED) when (action) { Intent.ACTION_SCREEN_OFF -> { - setVisible(visible && Build.VERSION.SDK_INT < 21, forceShow) + setVisible(false, forceShow) unregisterCallback() // unregister callback to save battery } Intent.ACTION_SCREEN_ON -> { - setVisible(visible && (Build.VERSION.SDK_INT < 21 || !keyGuard.inKeyguardRestrictedInputMode()), - forceShow) + setVisible(visible && !keyGuard.inKeyguardRestrictedInputMode(), forceShow) service.data.binder.registerCallback(callback) service.data.binder.startListeningForBandwidth(callback) callbackRegistered = true diff --git a/mobile/src/main/java/com/github/shadowsocks/bg/VpnService.kt b/mobile/src/main/java/com/github/shadowsocks/bg/VpnService.kt index 4a456d5a..ca3055f3 100644 --- a/mobile/src/main/java/com/github/shadowsocks/bg/VpnService.kt +++ b/mobile/src/main/java/com/github/shadowsocks/bg/VpnService.kt @@ -24,7 +24,6 @@ import android.app.Service import android.content.Intent import android.content.pm.PackageManager import android.net.LocalSocket -import android.os.Build import android.os.IBinder import android.os.ParcelFileDescriptor import android.util.Log @@ -140,7 +139,7 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface { builder.addRoute("::", 0) } - if (Build.VERSION.SDK_INT >= 21 && profile.proxyApps) { + if (profile.proxyApps) { val me = packageName profile.individual.split('\n') .filter { it != me } diff --git a/mobile/src/main/java/com/github/shadowsocks/tasker/ConfigActivity.kt b/mobile/src/main/java/com/github/shadowsocks/tasker/ConfigActivity.kt index 68afd7c4..602f75d7 100644 --- a/mobile/src/main/java/com/github/shadowsocks/tasker/ConfigActivity.kt +++ b/mobile/src/main/java/com/github/shadowsocks/tasker/ConfigActivity.kt @@ -22,7 +22,6 @@ package com.github.shadowsocks.tasker import android.app.Activity import android.content.res.Resources -import android.os.Build import android.os.Bundle import android.support.v7.app.AppCompatActivity import android.support.v7.widget.DefaultItemAnimator @@ -71,13 +70,12 @@ class ConfigActivity : AppCompatActivity() { inner class ProfilesAdapter : RecyclerView.Adapter() { internal val profiles = ProfileManager.getAllProfiles()?.toMutableList() ?: mutableListOf() - private val name = "select_dialog_singlechoice_" + (if (Build.VERSION.SDK_INT >= 21) "material" else "holo") override fun onBindViewHolder(holder: ProfileViewHolder, position: Int) = if (position == 0) holder.bindDefault() else holder.bind(profiles[position - 1]) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProfileViewHolder = ProfileViewHolder( LayoutInflater.from(parent.context).inflate(Resources.getSystem() - .getIdentifier(name, "layout", "android"), parent, false)) + .getIdentifier("select_dialog_singlechoice_material", "layout", "android"), parent, false)) override fun getItemCount(): Int = 1 + profiles.size } diff --git a/mobile/src/main/res/drawable-hdpi/ic_navigation_close.webp b/mobile/src/main/res/drawable-hdpi/ic_navigation_close.webp deleted file mode 100644 index 541301f0..00000000 Binary files a/mobile/src/main/res/drawable-hdpi/ic_navigation_close.webp and /dev/null differ diff --git a/mobile/src/main/res/drawable-hdpi/ic_service_active.webp b/mobile/src/main/res/drawable-hdpi/ic_service_active.webp deleted file mode 100644 index 65182a59..00000000 Binary files a/mobile/src/main/res/drawable-hdpi/ic_service_active.webp and /dev/null differ diff --git a/mobile/src/main/res/drawable-mdpi/ic_navigation_close.webp b/mobile/src/main/res/drawable-mdpi/ic_navigation_close.webp deleted file mode 100644 index 2c66e486..00000000 Binary files a/mobile/src/main/res/drawable-mdpi/ic_navigation_close.webp and /dev/null differ diff --git a/mobile/src/main/res/drawable-mdpi/ic_service_active.webp b/mobile/src/main/res/drawable-mdpi/ic_service_active.webp deleted file mode 100644 index 0182a994..00000000 Binary files a/mobile/src/main/res/drawable-mdpi/ic_service_active.webp and /dev/null differ diff --git a/mobile/src/main/res/drawable-v21/background_profile.xml b/mobile/src/main/res/drawable-v21/background_profile.xml deleted file mode 100644 index 3509fa32..00000000 --- a/mobile/src/main/res/drawable-v21/background_profile.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/mobile/src/main/res/drawable-v21/background_selectable.xml b/mobile/src/main/res/drawable-v21/background_selectable.xml deleted file mode 100644 index b8810034..00000000 --- a/mobile/src/main/res/drawable-v21/background_selectable.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - diff --git a/mobile/src/main/res/drawable-v21/background_stat.xml b/mobile/src/main/res/drawable-v21/background_stat.xml deleted file mode 100644 index 48bdd29f..00000000 --- a/mobile/src/main/res/drawable-v21/background_stat.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/mobile/src/main/res/drawable-xhdpi/ic_navigation_close.webp b/mobile/src/main/res/drawable-xhdpi/ic_navigation_close.webp deleted file mode 100644 index c1d0fd16..00000000 Binary files a/mobile/src/main/res/drawable-xhdpi/ic_navigation_close.webp and /dev/null differ diff --git a/mobile/src/main/res/drawable-xhdpi/ic_service_active.webp b/mobile/src/main/res/drawable-xhdpi/ic_service_active.webp deleted file mode 100644 index 0e0bbf50..00000000 Binary files a/mobile/src/main/res/drawable-xhdpi/ic_service_active.webp and /dev/null differ diff --git a/mobile/src/main/res/drawable-xxhdpi/ic_navigation_close.webp b/mobile/src/main/res/drawable-xxhdpi/ic_navigation_close.webp deleted file mode 100644 index 1ae09899..00000000 Binary files a/mobile/src/main/res/drawable-xxhdpi/ic_navigation_close.webp and /dev/null differ diff --git a/mobile/src/main/res/drawable-xxhdpi/ic_service_active.webp b/mobile/src/main/res/drawable-xxhdpi/ic_service_active.webp deleted file mode 100644 index bb2c5bc2..00000000 Binary files a/mobile/src/main/res/drawable-xxhdpi/ic_service_active.webp and /dev/null differ diff --git a/mobile/src/main/res/drawable-xxxhdpi/ic_navigation_close.webp b/mobile/src/main/res/drawable-xxxhdpi/ic_navigation_close.webp deleted file mode 100644 index 439b8fe8..00000000 Binary files a/mobile/src/main/res/drawable-xxxhdpi/ic_navigation_close.webp and /dev/null differ diff --git a/mobile/src/main/res/drawable/background_profile.xml b/mobile/src/main/res/drawable/background_profile.xml index 28592514..3509fa32 100644 --- a/mobile/src/main/res/drawable/background_profile.xml +++ b/mobile/src/main/res/drawable/background_profile.xml @@ -15,18 +15,11 @@ - + + - - - - - - - - - + diff --git a/mobile/src/main/res/drawable/background_selectable.xml b/mobile/src/main/res/drawable/background_selectable.xml index c969f4ac..b8810034 100644 --- a/mobile/src/main/res/drawable/background_selectable.xml +++ b/mobile/src/main/res/drawable/background_selectable.xml @@ -1,11 +1,12 @@ - - - + + + + + + + - - - - + + diff --git a/mobile/src/main/res/drawable/background_stat.xml b/mobile/src/main/res/drawable/background_stat.xml index fe7ba6d4..7c56f04c 100644 --- a/mobile/src/main/res/drawable/background_stat.xml +++ b/mobile/src/main/res/drawable/background_stat.xml @@ -1,17 +1,7 @@ - - - - - - - - - - - - + + diff --git a/mobile/src/main/res/drawable-anydpi-v21/ic_navigation_close.xml b/mobile/src/main/res/drawable/ic_navigation_close.xml similarity index 100% rename from mobile/src/main/res/drawable-anydpi-v21/ic_navigation_close.xml rename to mobile/src/main/res/drawable/ic_navigation_close.xml diff --git a/mobile/src/main/res/drawable-anydpi-v21/ic_service_active.xml b/mobile/src/main/res/drawable/ic_service_active.xml similarity index 100% rename from mobile/src/main/res/drawable-anydpi-v21/ic_service_active.xml rename to mobile/src/main/res/drawable/ic_service_active.xml diff --git a/mobile/src/main/res/layout/layout_main.xml b/mobile/src/main/res/layout/layout_main.xml index 480022ba..85a0de78 100644 --- a/mobile/src/main/res/layout/layout_main.xml +++ b/mobile/src/main/res/layout/layout_main.xml @@ -148,7 +148,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="16dp" - android:layout_marginTop="@dimen/fab_margin_top" + android:layout_marginTop="-28dp" android:elevation="6dp" app:layout_anchor="@id/stat" app:layout_anchorGravity="top|end"> diff --git a/mobile/src/main/res/values-v21/dimen.xml b/mobile/src/main/res/values-v21/dimen.xml deleted file mode 100644 index 605379c3..00000000 --- a/mobile/src/main/res/values-v21/dimen.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - -28dp - diff --git a/mobile/src/main/res/values/dimen.xml b/mobile/src/main/res/values/dimen.xml index ce2156f8..522ab6ce 100644 --- a/mobile/src/main/res/values/dimen.xml +++ b/mobile/src/main/res/values/dimen.xml @@ -4,5 +4,4 @@ 250dp 8dp 8dp - -44dp diff --git a/plugin/build.gradle b/plugin/build.gradle index 6c9c6336..19ec80ad 100644 --- a/plugin/build.gradle +++ b/plugin/build.gradle @@ -24,7 +24,6 @@ android { } dependencies { - api "com.android.support:preference-v7:$supportLibraryVersion" api "com.android.support:preference-v14:$supportLibraryVersion" api "com.takisoft.fix:preference-v7:$takisoftFixVersion" api "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlinVersion"