diff --git a/CMakeLists.txt b/CMakeLists.txt index 18c32f30..5b2885f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR) set(PROJECT AmneziaVPN) -project(${PROJECT} VERSION 4.4.2.1 +project(${PROJECT} VERSION 4.4.2.2 DESCRIPTION "AmneziaVPN" HOMEPAGE_URL "https://amnezia.org/" ) @@ -11,7 +11,7 @@ string(TIMESTAMP CURRENT_DATE "%Y-%m-%d") set(RELEASE_DATE "${CURRENT_DATE}") set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH}) -set(APP_ANDROID_VERSION_CODE 49) +set(APP_ANDROID_VERSION_CODE 50) if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") set(MZ_PLATFORM_NAME "linux") diff --git a/client/android/res/values-ru/strings.xml b/client/android/res/values-ru/strings.xml index f0070c0e..53cb9c45 100644 --- a/client/android/res/values-ru/strings.xml +++ b/client/android/res/values-ru/strings.xml @@ -2,4 +2,11 @@ Подключение Отключение + Отмена + ОК + VPN-подключение разрешено + VPN-подключение запрещено + Ошибка настройки VPN + Чтобы подключиться к AmneziaVPN необходимо:\n\n- Разрешить приложению подключаться к сети VPN\n- Отключить функцию \"Постоянная VPN\" для всех остальных VPN-приложений в системных настройках VPN + Открыть настройки VPN \ No newline at end of file diff --git a/client/android/res/values/strings.xml b/client/android/res/values/strings.xml index 3fdd9844..9172d14b 100644 --- a/client/android/res/values/strings.xml +++ b/client/android/res/values/strings.xml @@ -2,4 +2,11 @@ Connecting Disconnecting + Cancel + OK + VPN permission granted + VPN permission denied + VPN setup error + To connect to AmneziaVPN, please do the following:\n\n- Allow the app to set up a VPN connection\n- Disable Always-on VPN for any other VPN app in the VPN system settings + Open VPN settings \ No newline at end of file diff --git a/client/android/src/org/amnezia/vpn/AmneziaActivity.kt b/client/android/src/org/amnezia/vpn/AmneziaActivity.kt index ff25ab05..ef31a7d2 100644 --- a/client/android/src/org/amnezia/vpn/AmneziaActivity.kt +++ b/client/android/src/org/amnezia/vpn/AmneziaActivity.kt @@ -1,5 +1,6 @@ package org.amnezia.vpn +import android.app.AlertDialog import android.content.ComponentName import android.content.Intent import android.content.Intent.EXTRA_MIME_TYPES @@ -14,6 +15,7 @@ import android.os.IBinder import android.os.Looper import android.os.Message import android.os.Messenger +import android.provider.Settings import android.view.WindowManager.LayoutParams import android.webkit.MimeTypeMap import android.widget.Toast @@ -216,13 +218,13 @@ class AmneziaActivity : QtActivity() { when (resultCode) { RESULT_OK -> { Log.d(TAG, "Vpn permission granted") - Toast.makeText(this, "Vpn permission granted", Toast.LENGTH_LONG).show() + Toast.makeText(this, resources.getText(R.string.vpnGranted), Toast.LENGTH_LONG).show() checkVpnPermissionCallbacks?.run { onSuccess() } } else -> { Log.w(TAG, "Vpn permission denied, resultCode: $resultCode") - Toast.makeText(this, "Vpn permission denied", Toast.LENGTH_LONG).show() + showOnVpnPermissionRejectDialog() checkVpnPermissionCallbacks?.run { onFail() } } } @@ -280,6 +282,17 @@ class AmneziaActivity : QtActivity() { onSuccess() } + private fun showOnVpnPermissionRejectDialog() { + AlertDialog.Builder(this) + .setTitle(R.string.vpnSetupFailed) + .setMessage(R.string.vpnSetupFailedMessage) + .setNegativeButton(R.string.ok) { _, _ -> } + .setPositiveButton(R.string.openVpnSettings) { _, _ -> + startActivity(Intent(Settings.ACTION_VPN_SETTINGS)) + } + .show() + } + @MainThread private fun startVpn(vpnConfig: String) { if (isServiceConnected) { diff --git a/client/android/src/org/amnezia/vpn/AmneziaVpnService.kt b/client/android/src/org/amnezia/vpn/AmneziaVpnService.kt index 094383e8..d0a1e8e8 100644 --- a/client/android/src/org/amnezia/vpn/AmneziaVpnService.kt +++ b/client/android/src/org/amnezia/vpn/AmneziaVpnService.kt @@ -215,11 +215,9 @@ class AmneziaVpnService : VpnService() { } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - val isAlwaysOnCompat = - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) isAlwaysOn - else intent?.component?.packageName != packageName + val isAlwaysOn = intent != null && intent.action == SERVICE_INTERFACE - if (isAlwaysOnCompat) { + if (isAlwaysOn) { Log.d(TAG, "Start service via Always-on") connect() } else if (intent?.getBooleanExtra(AFTER_PERMISSION_CHECK, false) == true) { diff --git a/client/android/src/org/amnezia/vpn/VpnRequestActivity.kt b/client/android/src/org/amnezia/vpn/VpnRequestActivity.kt index c5abbc39..74aeb578 100644 --- a/client/android/src/org/amnezia/vpn/VpnRequestActivity.kt +++ b/client/android/src/org/amnezia/vpn/VpnRequestActivity.kt @@ -1,12 +1,16 @@ package org.amnezia.vpn +import android.app.AlertDialog import android.app.KeyguardManager import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter +import android.content.res.Configuration.UI_MODE_NIGHT_MASK +import android.content.res.Configuration.UI_MODE_NIGHT_YES import android.net.VpnService import android.os.Bundle +import android.provider.Settings import android.widget.Toast import androidx.activity.ComponentActivity import androidx.activity.result.ActivityResult @@ -52,19 +56,43 @@ class VpnRequestActivity : ComponentActivity() { } private fun checkRequestResult(result: ActivityResult) { - when (result.resultCode) { - RESULT_OK -> onPermissionGranted() - else -> Toast.makeText(this, "Vpn permission denied", Toast.LENGTH_LONG).show() + when (val resultCode = result.resultCode) { + RESULT_OK -> { + onPermissionGranted() + finish() + } + + else -> { + Log.w(TAG, "Vpn permission denied, resultCode: $resultCode") + showOnVpnPermissionRejectDialog() + } } - finish() } private fun onPermissionGranted() { - Toast.makeText(this, "Vpn permission granted", Toast.LENGTH_LONG).show() + Toast.makeText(this, resources.getString(R.string.vpnGranted), Toast.LENGTH_LONG).show() Intent(applicationContext, AmneziaVpnService::class.java).apply { putExtra(AFTER_PERMISSION_CHECK, true) }.also { ContextCompat.startForegroundService(this, it) } } + + private fun showOnVpnPermissionRejectDialog() { + AlertDialog.Builder(this, getDialogTheme()) + .setTitle(R.string.vpnSetupFailed) + .setMessage(R.string.vpnSetupFailedMessage) + .setNegativeButton(R.string.ok) { _, _ -> } + .setPositiveButton(R.string.openVpnSettings) { _, _ -> + startActivity(Intent(Settings.ACTION_VPN_SETTINGS)) + } + .setOnDismissListener { finish() } + .show() + } + + private fun getDialogTheme(): Int = + if (resources.configuration.uiMode and UI_MODE_NIGHT_MASK == UI_MODE_NIGHT_YES) + android.R.style.Theme_DeviceDefault_Dialog_Alert + else + android.R.style.Theme_DeviceDefault_Light_Dialog_Alert } diff --git a/client/android/wireguard/src/main/kotlin/org/amnezia/vpn/protocol/wireguard/Wireguard.kt b/client/android/wireguard/src/main/kotlin/org/amnezia/vpn/protocol/wireguard/Wireguard.kt index 95ea9aca..9b54cfb5 100644 --- a/client/android/wireguard/src/main/kotlin/org/amnezia/vpn/protocol/wireguard/Wireguard.kt +++ b/client/android/wireguard/src/main/kotlin/org/amnezia/vpn/protocol/wireguard/Wireguard.kt @@ -157,7 +157,7 @@ open class Wireguard : Protocol() { if (tunFd == null) { throw VpnStartException("Create VPN interface: permission not granted or revoked") } - Log.v(TAG, "Wg-go backend ${GoBackend.awgVersion()}") + Log.i(TAG, "awg-go backend ${GoBackend.awgVersion()}") tunnelHandle = GoBackend.awgTurnOn(ifName, tunFd.detachFd(), config.toWgUserspaceString()) } diff --git a/client/cmake/android.cmake b/client/cmake/android.cmake index fe4a607c..20fc617d 100644 --- a/client/cmake/android.cmake +++ b/client/cmake/android.cmake @@ -42,9 +42,7 @@ set(SOURCES ${SOURCES} foreach(abi IN ITEMS ${QT_ANDROID_ABIS}) set_property(TARGET ${PROJECT} PROPERTY QT_ANDROID_EXTRA_LIBS - ${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/amneziawg/android/${abi}/libwg.so ${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/amneziawg/android/${abi}/libwg-go.so - ${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/amneziawg/android/${abi}/libwg-quick.so ${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/openvpn/android/${abi}/libck-ovpn-plugin.so ${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/openvpn/android/${abi}/libovpn3.so ${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/openvpn/android/${abi}/libovpnutil.so