summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcyberta <cyberta@riseup.net>2022-12-26 14:12:10 +0000
committercyberta <cyberta@riseup.net>2022-12-26 14:12:10 +0000
commit9d64ea1f6274ca66c4e44f7bd24698a1f64c3ffe (patch)
tree1bf433d5363a437d388851e7368ee143a226f6b7
parent6334225050f02901119812b807c29a4a07ebe182 (diff)
parent35bd57e5399e8bec5102338c7f0900fbc18970b2 (diff)
Merge branch 'rc_fixes' into 'master'
Rc fixes See merge request leap/bitmask_android!235
-rw-r--r--README.md17
-rw-r--r--app/src/main/java/de/blinkt/openvpn/VpnProfile.java40
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java2
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java29
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/NetworkUtils.java68
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java38
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java19
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java15
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java22
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/fragments/TetheringDialog.java10
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/utils/ViewHelper.java10
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java13
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/VpnNotificationManager.java75
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ConfigWizardBaseActivity.java11
-rw-r--r--app/src/main/res/layout-port/f_eip.xml8
-rw-r--r--app/src/main/res/layout-sw600dp-port/f_eip.xml6
-rw-r--r--app/src/main/res/layout-xlarge-port/f_eip.xml3
-rw-r--r--app/src/main/res/layout/donation_reminder_dialog.xml4
-rw-r--r--app/src/main/res/values-fr/strings.xml2
-rw-r--r--app/src/main/res/values-gl/strings.xml2
-rw-r--r--app/src/main/res/values-pt-rBR/strings.xml2
-rw-r--r--app/src/main/res/values-sw600dp/dimens.xml2
-rw-r--r--app/src/main/res/values-w820dp/dimens.xml2
-rw-r--r--app/src/main/res/values-zh-rCN/strings.xml2
-rw-r--r--app/src/main/res/values/colors.xml2
-rw-r--r--app/src/main/res/values/dimens.xml4
-rw-r--r--docker/android-ndk/Dockerfile2
m---------tor-android0
28 files changed, 120 insertions, 290 deletions
diff --git a/README.md b/README.md
index 97803817..823eb48b 100644
--- a/README.md
+++ b/README.md
@@ -104,7 +104,7 @@ export PATH=$ANDROID_HOME/tools/bin:$PATH
Geesh! If all that above seems like a lot, it is!
-To keep ourselves from messing it up all the time someone new joins the project, we made a Dockerfile that creates the above environment with one line. You can pull the image and run builds from inside it, or consult the [Dockerfile](/docker/android-sdk.dockerfile) itself for requirements that your system might need but be missing.
+To keep ourselves from messing it up all the time someone new joins the project, we made a Dockerfile that creates the above environment with one line. You can pull the image and run builds from inside it, or consult [android-sdk Dockerfile](/docker/android-sdk/Dockerfile) and [android-ndk Dockerfile](/docker/android-ndk/Dockerfile) itself for requirements that your system might need but be missing.
Assuming you've already [installed docker](https://docs.docker.com/engine/installation/), you can pull the image with:
@@ -143,18 +143,23 @@ git submodule update --init --recursive
### Just Build It! <a name="just-build-it"></a>
-If you compile the project for the first time you'll have to compile the dependencies. This can be done with:
+If you compile the project for the first time you'll have to compile the dependencies.
+In order to get a clean build and fetch all submodules run:
+```
+./cleanProject.sh
+```
+The following command will create all libs we need for Bitmask.
```
./scripts/build_deps.sh
```
-This command will create all libs we need for Bitmask.
-If you want to to have a clean build of all submodules run
+If you run into errors, you may miss some dependencies on your system. Again, please check the `RUN apt-get` commands of [android-sdk Dockerfile](/docker/android-sdk/Dockerfile) and [android-ndk Dockerfile](/docker/android-ndk/Dockerfile) to get an idea what might be missing.
+Please note that tor-android can only be build on Linux machines right now. Fixes for Windows and MacOS are more than welcome!
+In order to temporarily disable building tor you can run:
```
-./cleanProject.sh
+BUILD_TOR=false ./scripts/build_deps.sh
```
-before you call `./build_deps.sh`. That script removes all build files and does the git submodule init and update job for you.
### Debug APKs <a name="debug-apks"></a>
diff --git a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java
index 7dd75432..83cde85e 100644
--- a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java
+++ b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java
@@ -473,9 +473,6 @@ public class VpnProfile implements Serializable, Cloneable {
cfg.append("management-external-key nopadding\n");
} else {
cfg.append(context.getString(R.string.keychain_access)).append("\n");
- if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN)
- if (!mAlias.matches("^[a-zA-Z0-9]$"))
- cfg.append(context.getString(R.string.jelly_keystore_alphanumeric_bug)).append("\n");
}
}
break;
@@ -932,11 +929,6 @@ public class VpnProfile implements Serializable, Cloneable {
VpnStatus.logError(R.string.keyChainAccessError, e.getLocalizedMessage());
VpnStatus.logError(R.string.keychain_access);
- if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN) {
- if (!mAlias.matches("^[a-zA-Z0-9]$")) {
- VpnStatus.logError(R.string.jelly_keystore_alphanumeric_bug);
- }
- }
return null;
} catch (AssertionError e) {
@@ -1196,12 +1188,6 @@ public class VpnProfile implements Serializable, Cloneable {
private byte[] getKeyChainSignedData(byte[] data, boolean pkcs1padding) {
PrivateKey privkey = getKeystoreKey();
- // The Jelly Bean *evil* Hack
- // 4.2 implements the RSA/ECB/PKCS1PADDING in the OpenSSLprovider
- if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN) {
- return processSignJellyBeans(privkey, data);
- }
-
try {
@SuppressLint("GetInstance")
@@ -1238,32 +1224,6 @@ public class VpnProfile implements Serializable, Cloneable {
}
}
- private byte[] processSignJellyBeans(PrivateKey privkey, byte[] data) {
- try {
- Method getKey = privkey.getClass().getSuperclass().getDeclaredMethod("getOpenSSLKey");
- getKey.setAccessible(true);
-
- // Real object type is OpenSSLKey
- Object opensslkey = getKey.invoke(privkey);
-
- getKey.setAccessible(false);
-
- Method getPkeyContext = opensslkey.getClass().getDeclaredMethod("getPkeyContext");
-
- // integer pointer to EVP_pkey
- getPkeyContext.setAccessible(true);
- int pkey = (Integer) getPkeyContext.invoke(opensslkey);
- getPkeyContext.setAccessible(false);
-
- // 112 with TLS 1.2 (172 back with 4.3), 36 with TLS 1.0
- return NativeUtils.rsasign(data, pkey);
-
- } catch (NoSuchMethodException | InvalidKeyException | InvocationTargetException | IllegalAccessException | IllegalArgumentException e) {
- VpnStatus.logError(R.string.error_rsa_sign, e.getClass().toString(), e.getLocalizedMessage());
- return null;
- }
- }
-
private boolean usesExtraProxyOptions() {
if (mUseCustomConfig && mCustomConfigOptions != null && mCustomConfigOptions.contains("http-proxy-option "))
return true;
diff --git a/app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java b/app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java
index 5a1757ac..f769b38e 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/NativeUtils.java
@@ -38,8 +38,6 @@ public class NativeUtils {
static {
if (!isRoboUnitTest() && !isUnitTest()) {
System.loadLibrary("ovpnutil");
- if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN)
- System.loadLibrary("jbcrypto");
}
}
diff --git a/app/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java b/app/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java
index 860897db..457ae971 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/NetworkSpace.java
@@ -336,35 +336,6 @@ public class NetworkSpace {
ips.add(ia);
}
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
- // Include postive routes from the original set under < 4.4 since these might overrule the local
- // network but only if no smaller negative route exists
- for (IpAddress origIp : mIpAddresses) {
- if (!origIp.included)
- continue;
-
- // The netspace exists
- if (ipsSorted.contains(origIp))
- continue;
-
- boolean skipIp = false;
- // If there is any smaller net that is excluded we may not add the positive route back
-
- for (IpAddress calculatedIp : ipsSorted) {
- if (!calculatedIp.included && origIp.containsNet(calculatedIp)) {
- skipIp = true;
- break;
- }
- }
- if (skipIp)
- continue;
-
- // It is safe to include the IP
- ips.add(origIp);
- }
-
- }
-
return ips;
}
diff --git a/app/src/main/java/de/blinkt/openvpn/core/NetworkUtils.java b/app/src/main/java/de/blinkt/openvpn/core/NetworkUtils.java
index 5b11c0a0..25af6121 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/NetworkUtils.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/NetworkUtils.java
@@ -24,63 +24,35 @@ public class NetworkUtils {
public static Vector<String> getLocalNetworks(Context c, boolean ipv6) {
Vector<String> nets = new Vector<>();
ConnectivityManager conn = (ConnectivityManager) c.getSystemService(Context.CONNECTIVITY_SERVICE);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- Network[] networks = conn.getAllNetworks();
- for (Network network : networks) {
- try {
- NetworkInfo ni = conn.getNetworkInfo(network);
- LinkProperties li = conn.getLinkProperties(network);
+ Network[] networks = conn.getAllNetworks();
+ for (Network network : networks) {
+ try {
+ NetworkInfo ni = conn.getNetworkInfo(network);
+ LinkProperties li = conn.getLinkProperties(network);
- NetworkCapabilities nc = conn.getNetworkCapabilities(network);
+ NetworkCapabilities nc = conn.getNetworkCapabilities(network);
- if (nc == null) {
- continue;
- }
-
- // Skip VPN networks like ourselves
- if (nc.hasTransport(NetworkCapabilities.TRANSPORT_VPN))
- continue;
-
- // Also skip mobile networks
- if (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
- continue;
-
-
- for (LinkAddress la : li.getLinkAddresses()) {
- if ((la.getAddress() instanceof Inet4Address && !ipv6) ||
- (la.getAddress() instanceof Inet6Address && ipv6))
- nets.add(la.toString());
- }
- } catch (SecurityException se) {
- se.printStackTrace();
+ if (nc == null) {
+ continue;
}
- }
- } else {
- // Old Android Version, use native utils via ifconfig instead
- // Add local network interfaces
- if (ipv6)
- return nets;
- String[] localRoutes = NativeUtils.getIfconfig();
-
- // The format of mLocalRoutes is kind of broken because I don't really like JNI
- for (int i = 0; i < localRoutes.length; i += 3) {
- String intf = localRoutes[i];
- String ipAddr = localRoutes[i + 1];
- String netMask = localRoutes[i + 2];
-
- if (intf == null || intf.equals("lo") ||
- intf.startsWith("tun") || intf.startsWith("rmnet"))
+ // Skip VPN networks like ourselves
+ if (nc.hasTransport(NetworkCapabilities.TRANSPORT_VPN))
continue;
- if (ipAddr == null || netMask == null) {
- VpnStatus.logError("Local routes are broken?! (Report to author) " + TextUtils.join("|", localRoutes));
+ // Also skip mobile networks
+ if (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
continue;
- }
- nets.add(ipAddr + "/" + CIDRIP.calculateLenFromMask(netMask));
- }
+ for (LinkAddress la : li.getLinkAddresses()) {
+ if ((la.getAddress() instanceof Inet4Address && !ipv6) ||
+ (la.getAddress() instanceof Inet6Address && ipv6))
+ nets.add(la.toString());
+ }
+ } catch (SecurityException se) {
+ se.printStackTrace();
+ }
}
return nets;
}
diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
index 88a85de3..0ae7639e 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
@@ -589,7 +589,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
VpnStatus.logInfo(R.string.last_openvpn_tun_config);
- boolean allowUnsetAF = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !mProfile.mBlockUnusedAddressFamilies;
+ boolean allowUnsetAF = !mProfile.mBlockUnusedAddressFamilies;
if (allowUnsetAF) {
allowAllAFFamilies(builder);
}
@@ -631,20 +631,12 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
}
- String release = Build.VERSION.RELEASE;
- if ((Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT && !release.startsWith("4.4.3")
- && !release.startsWith("4.4.4") && !release.startsWith("4.4.5") && !release.startsWith("4.4.6"))
- && mMtu < 1280) {
- VpnStatus.logInfo(String.format(Locale.US, "Forcing MTU to 1280 instead of %d to workaround Android Bug #70916", mMtu));
- builder.setMtu(1280);
- } else {
- builder.setMtu(mMtu);
- }
+ builder.setMtu(mMtu);
Collection<IpAddress> positiveIPv4Routes = mRoutes.getPositiveIPList();
Collection<IpAddress> positiveIPv6Routes = mRoutesv6.getPositiveIPList();
- if ("samsung".equals(Build.BRAND) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mDnslist.size() >= 1) {
+ if ("samsung".equals(Build.BRAND) && mDnslist.size() >= 1) {
// Check if the first DNS Server is in the VPN range
try {
IpAddress dnsServer = new IpAddress(new CIDRIP(mDnslist.get(0), 32), true);
@@ -725,9 +717,8 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
VpnStatus.logInfo(R.string.routes_info_incl, TextUtils.join(", ", mRoutes.getNetworks(true)), TextUtils.join(", ", mRoutesv6.getNetworks(true)));
VpnStatus.logInfo(R.string.routes_info_excl, TextUtils.join(", ", mRoutes.getNetworks(false)), TextUtils.join(", ", mRoutesv6.getNetworks(false)));
VpnStatus.logDebug(R.string.routes_debug, TextUtils.join(", ", positiveIPv4Routes), TextUtils.join(", ", positiveIPv6Routes));
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- setAllowedVpnPackages(builder);
- }
+
+ setAllowedVpnPackages(builder);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
// VPN always uses the default network
builder.setUnderlyingNetworks(null);
@@ -773,9 +764,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
} catch (Exception e) {
VpnStatus.logError(R.string.tun_open_error);
VpnStatus.logError(getString(R.string.error) + e.getLocalizedMessage());
- if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- VpnStatus.logError(R.string.tun_error_helpful);
- }
return null;
}
@@ -790,7 +778,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
}
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void allowAllAFFamilies(Builder builder) {
builder.allowFamily(OsConstants.AF_INET);
builder.allowFamily(OsConstants.AF_INET6);
@@ -805,11 +792,9 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
if (ipAddr.equals(mLocalIP.mIp))
continue;
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT && !mProfile.mAllowLocalLAN) {
- mRoutes.addIPSplit(new CIDRIP(ipAddr, netMask), true);
-
- } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && mProfile.mAllowLocalLAN)
+ if (mProfile.mAllowLocalLAN) {
mRoutes.addIP(new CIDRIP(ipAddr, netMask), false);
+ }
}
// IPv6 is Lollipop+ only so we can skip the lower than KITKAT case
@@ -823,7 +808,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void setAllowedVpnPackages(Builder builder) {
boolean profileUsesOrBot = false;
@@ -1094,13 +1078,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
if (currentConfiguration.equals(mLastTunCfg)) {
return "NOACTION";
} else {
- String release = Build.VERSION.RELEASE;
- if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT && !release.startsWith("4.4.3")
- && !release.startsWith("4.4.4") && !release.startsWith("4.4.5") && !release.startsWith("4.4.6"))
- // There will be probably no 4.4.4 or 4.4.5 version, so don't waste effort to do parsing here
- return "OPEN_AFTER_CLOSE";
- else
- return "OPEN_BEFORE_CLOSE";
+ return "OPEN_BEFORE_CLOSE";
}
}
diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java
index 0edfeaeb..a02e7e27 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java
@@ -242,12 +242,10 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {
VpnStatus.logWarning("Could not protect VPN socket");
- //ParcelFileDescriptor pfd = ParcelFileDescriptor.fromFd(fdint);
- //pfd.close();
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- fdCloseLollipop(fd);
- } else {
- NativeUtils.jniclose(fdint);
+ try {
+ Os.close(fd);
+ } catch (Exception e) {
+ VpnStatus.logException("Failed to close fd (" + fd + ")", e);
}
return;
} catch ( NoSuchMethodException | IllegalArgumentException | InvocationTargetException | IllegalAccessException | NullPointerException e) {
@@ -258,15 +256,6 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {
}
- @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
- private void fdCloseLollipop(FileDescriptor fd) {
- try {
- Os.close(fd);
- } catch (Exception e) {
- VpnStatus.logException("Failed to close fd (" + fd + ")", e);
- }
- }
-
private String processInput(String pendingInput) {
diff --git a/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java b/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java
index 540ca043..80427a03 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java
@@ -30,11 +30,7 @@ public class VPNLaunchHelper {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
return new File(context.getApplicationInfo().nativeLibraryDir, "libovpnexec.so").getPath();
String[] abis;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
- abis = getSupportedABIsLollipop();
- else
- //noinspection deprecation
- abis = new String[]{Build.CPU_ABI, Build.CPU_ABI2};
+ abis = getSupportedABIsLollipop();
if (!nativeAPI.equals(abis[0])) {
VpnStatus.logWarning(R.string.abi_mismatch, Arrays.toString(abis), nativeAPI);
@@ -49,22 +45,17 @@ public class VPNLaunchHelper {
}
}
- throw new RuntimeException("Cannot find any execulte for this device's ABIs " + abis.toString());
+ throw new RuntimeException("Cannot find any execute for this device's ABIs " + abis.toString());
}
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static String[] getSupportedABIsLollipop() {
return Build.SUPPORTED_ABIS;
}
private static String getMiniVPNExecutableName() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
- return MINIPIEVPN;
- else
- return MININONPIEVPN;
+ return MINIPIEVPN;
}
-
public static String[] replacePieWithNoPie(String[] mArgv) {
mArgv[0] = mArgv[0].replace(MINIPIEVPN, MININONPIEVPN);
return mArgv;
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java
index d5bbd2c5..d57d725e 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java
@@ -174,19 +174,17 @@ public class SettingsFragment extends Fragment implements SharedPreferences.OnSh
}
private void initExcludeAppsEntry(View rootView) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- IconTextEntry excludeApps = rootView.findViewById(R.id.exclude_apps);
- excludeApps.setVisibility(VISIBLE);
- Set<String> apps = PreferenceHelper.getExcludedApps(this.getContext());
- if (apps != null) {
- updateExcludeAppsSubtitle(excludeApps, apps.size());
- }
- FragmentManagerEnhanced fragmentManager = new FragmentManagerEnhanced(getActivity().getSupportFragmentManager());
- excludeApps.setOnClickListener((buttonView) -> {
- Fragment fragment = new ExcludeAppsFragment();
- fragmentManager.replace(R.id.main_container, fragment, MainActivity.TAG);
- });
+ IconTextEntry excludeApps = rootView.findViewById(R.id.exclude_apps);
+ excludeApps.setVisibility(VISIBLE);
+ Set<String> apps = PreferenceHelper.getExcludedApps(this.getContext());
+ if (apps != null) {
+ updateExcludeAppsSubtitle(excludeApps, apps.size());
}
+ FragmentManagerEnhanced fragmentManager = new FragmentManagerEnhanced(getActivity().getSupportFragmentManager());
+ excludeApps.setOnClickListener((buttonView) -> {
+ Fragment fragment = new ExcludeAppsFragment();
+ fragmentManager.replace(R.id.main_container, fragment, MainActivity.TAG);
+ });
}
private void updateExcludeAppsSubtitle(IconTextEntry excludeApps, int number) {
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/TetheringDialog.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/TetheringDialog.java
index 675f1a61..e747d5b4 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/TetheringDialog.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/TetheringDialog.java
@@ -209,10 +209,18 @@ public class TetheringDialog extends AppCompatDialogFragment implements Observer
int endIndex = 0;
if (matcher.matches()) {
startIndex = matcher.start(2);
- endIndex = startIndex + matcher.group(3).length();
+ try {
+ endIndex = startIndex + matcher.group(3).length();
+ } catch (NullPointerException npe) {
+ endIndex = -1;
+ }
}
systemSettingsMessage = systemSettingsMessage.replace("<b>", "").replace("</b>", "");
String wholeMessage = systemSettingsMessage + "\n\n" + tetheringMessage;
+ if (startIndex == -1 || endIndex == -1) {
+ Log.e(TAG, "Tethering string has wrong formatting!");
+ return wholeMessage;
+ }
Spannable spannable = new SpannableString(wholeMessage);
spannable.setSpan(new ClickableSpan() {
@Override
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/ViewHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/ViewHelper.java
index 8f4d7862..51bcb2b1 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/utils/ViewHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/ViewHelper.java
@@ -96,12 +96,10 @@ public class ViewHelper {
}
int color = ContextCompat.getColor(activity, secondaryColor);
bar.setBackgroundDrawable(new ColorDrawable(color));
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- Window window = activity.getWindow();
- window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
- window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
- window.setStatusBarColor(ContextCompat.getColor(activity, primaryColor));
- }
+ Window window = activity.getWindow();
+ window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+ window.setStatusBarColor(ContextCompat.getColor(activity, primaryColor));
int actionBarTextColor;
if (textColor == 0) {
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java
index 645d7b26..79876d50 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java
@@ -91,7 +91,7 @@ public class VoidVpnService extends VpnService implements Observer, VpnNotificat
}
});
thread.run();
- } else if (action.equals("android.net.VpnService") && Build.VERSION.SDK_INT >= ALWAYS_ON_MIN_API_LEVEL) {
+ } else if (intent == null || action.equals("android.net.VpnService") && Build.VERSION.SDK_INT >= ALWAYS_ON_MIN_API_LEVEL) {
//only always-on feature triggers this
startWithForegroundNotification();
thread = new Thread(new Runnable() {
@@ -154,15 +154,12 @@ public class VoidVpnService extends VpnService implements Observer, VpnNotificat
builder.addRoute("::",0);
builder.addAddress("fc00::", 7);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- allowAllAFFamilies(builder);
- }
+ allowAllAFFamilies(builder);
return builder;
}
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void allowAllAFFamilies(Builder builder) {
builder.allowFamily(OsConstants.AF_INET);
builder.allowFamily(OsConstants.AF_INET6);
@@ -174,9 +171,7 @@ public class VoidVpnService extends VpnService implements Observer, VpnNotificat
VpnStatus.updateStateString(STATE_ESTABLISH, "",
R.string.void_vpn_establish, ConnectionStatus.LEVEL_BLOCKING);
Builder builder = prepareBlockingVpnProfile();
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- builder.addDisallowedApplication(getPackageName());
- }
+ builder.addDisallowedApplication(getPackageName());
fd = builder.establish();
} catch (Exception e) {
@@ -208,7 +203,7 @@ public class VoidVpnService extends VpnService implements Observer, VpnNotificat
blockingMessage,
blockingMessage,
eipStatus.getLevel(),
- this
+ null
);
} else {
stopForeground(true);
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VpnNotificationManager.java b/app/src/main/java/se/leap/bitmaskclient/eip/VpnNotificationManager.java
index 31893fb1..b4d11f26 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnNotificationManager.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnNotificationManager.java
@@ -16,6 +16,18 @@
*/
package se.leap.bitmaskclient.eip;
+import static android.os.Build.VERSION_CODES.O;
+import static android.text.TextUtils.isEmpty;
+import static androidx.core.app.NotificationCompat.PRIORITY_DEFAULT;
+import static androidx.core.app.NotificationCompat.PRIORITY_MAX;
+import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_NONETWORK;
+import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT;
+import static se.leap.bitmaskclient.base.MainActivity.ACTION_SHOW_VPN_FRAGMENT;
+import static se.leap.bitmaskclient.base.models.Constants.ASK_TO_CANCEL_VPN;
+import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START;
+import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_STOP_BLOCKING_VPN;
+import static se.leap.bitmaskclient.base.utils.ConfigHelper.getPendingIntentFlags;
+
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationChannel;
@@ -31,7 +43,6 @@ import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.StyleSpan;
-import android.widget.RemoteViews;
import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat;
@@ -45,18 +56,6 @@ import se.leap.bitmaskclient.R;
import se.leap.bitmaskclient.base.MainActivity;
import se.leap.bitmaskclient.base.StartActivity;
-import static android.os.Build.VERSION_CODES.O;
-import static android.text.TextUtils.isEmpty;
-import static androidx.core.app.NotificationCompat.PRIORITY_DEFAULT;
-import static androidx.core.app.NotificationCompat.PRIORITY_MAX;
-import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_NONETWORK;
-import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT;
-import static se.leap.bitmaskclient.base.MainActivity.ACTION_SHOW_VPN_FRAGMENT;
-import static se.leap.bitmaskclient.base.models.Constants.ASK_TO_CANCEL_VPN;
-import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START;
-import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_STOP_BLOCKING_VPN;
-import static se.leap.bitmaskclient.base.utils.ConfigHelper.getPendingIntentFlags;
-
/**
* Created by cyberta on 14.01.18.
*/
@@ -129,7 +128,7 @@ public class VpnNotificationManager {
public void buildOpenVpnNotification(String profileName, boolean isObfuscated, String msg,
String tickerText, ConnectionStatus status, long when,
- String notificationChannelNewstatusId, VpnServiceCallback vpnServiceCallback) {
+ String channelId, VpnServiceCallback vpnServiceCallback) {
String cancelString;
CharSequence bigmessage = null;
String bridgeIcon = new String(Character.toChars(0x1f309));
@@ -141,7 +140,7 @@ public class VpnNotificationManager {
case LEVEL_CONNECTING_SERVER_REPLIED:
case LEVEL_CONNECTING_NO_SERVER_REPLY_YET:
cancelString = context.getString(R.string.cancel);
- if (isObfuscated && Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {
+ if (isObfuscated) {
Spannable spannable = new SpannableString(context.getString(R.string.obfuscated_connection_try));
spannable.setSpan(new StyleSpan(Typeface.ITALIC), 0, spannable.length() -1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
bigmessage = TextUtils.concat(spannable, " " + bridgeIcon + "\n" + msg);
@@ -150,7 +149,7 @@ public class VpnNotificationManager {
// show disconnect if connection exists
case LEVEL_CONNECTED:
- if (isObfuscated && Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {
+ if (isObfuscated) {
Spannable spannable = new SpannableString(context.getString(R.string.obfuscated_connection));
spannable.setSpan(new StyleSpan(Typeface.ITALIC), 0, spannable.length() -1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
bigmessage = TextUtils.concat(spannable, " " + bridgeIcon + "\n" + msg);
@@ -184,7 +183,7 @@ public class VpnNotificationManager {
bigmessage,
tickerText,
status,
- notificationChannelNewstatusId,
+ channelId,
PRIORITY_DEFAULT,
when,
contentIntent,
@@ -245,40 +244,16 @@ public class VpnNotificationManager {
}
}
- /**
- * @return a custom remote view for notifications for API 16 - 19
- */
- private RemoteViews getKitkatCustomRemoteView(ConnectionStatus status, String title, String message) {
- int iconResource = getIconByConnectionStatus(status);
- RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.v_custom_notification);
- remoteViews.setImageViewResource(R.id.image_icon, iconResource);
- remoteViews.setTextViewText(R.id.message, message);
- remoteViews.setTextViewText(R.id.title, title);
-
- return remoteViews;
- }
-
private void buildVpnNotification(String title, String message, CharSequence bigMessage, String tickerText,
- ConnectionStatus status, String notificationChannelNewstatusId, int priority,
+ ConnectionStatus status, String channelId, int priority,
long when, PendingIntent contentIntent, NotificationCompat.Action notificationAction, VpnServiceCallback vpnServiceCallback) {
- NotificationCompat.Builder nCompatBuilder = new NotificationCompat.Builder(context, notificationChannelNewstatusId);
+ NotificationCompat.Builder nCompatBuilder = new NotificationCompat.Builder(context, channelId);
int icon = getIconByConnectionStatus(status);
- // this is a workaround to avoid confusion between the Android's system vpn notification
- // showing a filled out key icon and the bitmask icon indicating a different state.
- if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT &&
- notificationChannelNewstatusId.equals(OpenVPNService.NOTIFICATION_CHANNEL_NEWSTATUS_ID)) {
- if (status != LEVEL_NONETWORK) {
- // removes the icon from the system status bar
- icon = android.R.color.transparent;
- // adds the icon to the notification in the notification drawer
- nCompatBuilder.setContent(getKitkatCustomRemoteView(status, title, message));
- }
- } else {
- nCompatBuilder.setStyle(new NotificationCompat.BigTextStyle().
- setBigContentTitle(title).
- bigText(bigMessage));
- }
+ nCompatBuilder.setStyle(new NotificationCompat.BigTextStyle().
+ setBigContentTitle(title).
+ bigText(bigMessage));
+
nCompatBuilder.addAction(notificationAction);
nCompatBuilder.setContentTitle(title);
nCompatBuilder.setCategory(NotificationCompat.CATEGORY_SERVICE);
@@ -296,11 +271,13 @@ public class VpnNotificationManager {
}
Notification notification = nCompatBuilder.build();
- int notificationId = notificationChannelNewstatusId.hashCode();
+ int notificationId = channelId.hashCode();
- compatNotificationManager.notify(notificationId, notification);
if (vpnServiceCallback != null) {
vpnServiceCallback.onNotificationBuild(notificationId, notification);
+ } else {
+ compatNotificationManager.notify(notificationId, notification);
+
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ConfigWizardBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ConfigWizardBaseActivity.java
index aaf20647..5cfefb2e 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ConfigWizardBaseActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ConfigWizardBaseActivity.java
@@ -161,7 +161,6 @@ public abstract class ConfigWizardBaseActivity extends ButterKnifeActivity imple
if (provider != null) {
setProviderHeaderText(provider.getName());
}
- setProgressbarColorForPreLollipop();
setDefaultGuidelineValues();
setGlobalLayoutChangeListener();
}
@@ -173,16 +172,6 @@ public abstract class ConfigWizardBaseActivity extends ButterKnifeActivity imple
}
}
- private void setProgressbarColorForPreLollipop() {
- if (progressBar == null || Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- return;
- }
- progressBar.getIndeterminateDrawable().setColorFilter(
- ContextCompat.getColor(this, R.color.colorPrimary),
- PorterDuff.Mode.SRC_IN);
- }
-
-
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
diff --git a/app/src/main/res/layout-port/f_eip.xml b/app/src/main/res/layout-port/f_eip.xml
index 80f42f91..e14c7a10 100644
--- a/app/src/main/res/layout-port/f_eip.xml
+++ b/app/src/main/res/layout-port/f_eip.xml
@@ -64,8 +64,6 @@
android:scaleType="fitXY"
/>
-
-
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/main_description"
android:layout_width="wrap_content"
@@ -78,9 +76,7 @@
android:layout_marginTop="@dimen/activity_margin"
android:textAppearance="@android:style/TextAppearance.Large"
android:textStyle="bold"
- android:textSize="34sp"
- app:autoSizeMinTextSize="28sp"
- app:autoSizeTextType="uniform"
+ android:textSize="32sp"
android:textColor="@color/colorEipFragmentFont"
app:layout_constraintDimensionRatio="1:1"
tools:text="Connection secure"
@@ -122,7 +118,7 @@
android:id="@+id/main_button"
android:layout_width="0dp"
android:layout_height="0dp"
- android:layout_margin="@dimen/stdpadding"
+ android:layout_margin="@dimen/mainbutton_padding"
app:layout_constraintTop_toBottomOf="@+id/guideline_horizontal_bottom"
app:layout_constraintBottom_toTopOf="@id/gateway_location_button"
app:layout_constraintDimensionRatio="1:1"
diff --git a/app/src/main/res/layout-sw600dp-port/f_eip.xml b/app/src/main/res/layout-sw600dp-port/f_eip.xml
index 93393565..88e51652 100644
--- a/app/src/main/res/layout-sw600dp-port/f_eip.xml
+++ b/app/src/main/res/layout-sw600dp-port/f_eip.xml
@@ -77,13 +77,11 @@
android:textAppearance="@android:style/TextAppearance.Large"
android:textStyle="bold"
android:textSize="48sp"
- app:autoSizeMinTextSize="32sp"
- app:autoSizeTextType="uniform"
android:textColor="@color/colorEipFragmentFont"
app:layout_constraintDimensionRatio="1:1"
tools:text="Connection secure"
android:gravity="center"
- android:maxLines="1"
+ android:maxLines="2"
/>
<androidx.appcompat.widget.AppCompatTextView
@@ -120,7 +118,7 @@
android:id="@+id/main_button"
android:layout_width="0dp"
android:layout_height="0dp"
- android:layout_margin="@dimen/stdpadding"
+ android:layout_margin="@dimen/mainbutton_padding"
app:layout_constraintTop_toBottomOf="@+id/guideline_horizontal_bottom"
app:layout_constraintBottom_toTopOf="@id/gateway_location_button"
app:layout_constraintDimensionRatio="1:1"
diff --git a/app/src/main/res/layout-xlarge-port/f_eip.xml b/app/src/main/res/layout-xlarge-port/f_eip.xml
index ee0fbac9..590cf1a4 100644
--- a/app/src/main/res/layout-xlarge-port/f_eip.xml
+++ b/app/src/main/res/layout-xlarge-port/f_eip.xml
@@ -83,6 +83,7 @@
android:textColor="@color/colorEipFragmentFont"
app:layout_constraintDimensionRatio="1:1"
tools:text="Connection secure"
+ android:maxLines="2"
/>
<androidx.appcompat.widget.AppCompatTextView
@@ -123,7 +124,7 @@
android:id="@+id/main_button"
android:layout_width="0dp"
android:layout_height="0dp"
- android:layout_margin="@dimen/stdpadding"
+ android:layout_margin="@dimen/mainbutton_padding"
app:layout_constraintTop_toBottomOf="@id/guideline_horizontal_bottom"
app:layout_constraintBottom_toTopOf="@+id/guideline_horizontal_button_top"
app:layout_constraintEnd_toStartOf="@+id/guideline_vertical_right"
diff --git a/app/src/main/res/layout/donation_reminder_dialog.xml b/app/src/main/res/layout/donation_reminder_dialog.xml
index 17eaf009..1260a99e 100644
--- a/app/src/main/res/layout/donation_reminder_dialog.xml
+++ b/app/src/main/res/layout/donation_reminder_dialog.xml
@@ -30,7 +30,7 @@
android:id="@+id/tvMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_margin="@dimen/standard_margin"
+ android:layout_margin="@dimen/donation_reminder_padding"
android:gravity="center"
android:text="@string/donate_message" />
@@ -57,7 +57,7 @@
android:id="@+id/btnLater"
android:layout_width="200dp"
android:layout_height="38dp"
- android:layout_marginBottom="@dimen/mainbutton_padding"
+ android:layout_marginBottom="20dp"
android:layout_marginLeft="@dimen/add_button_margin"
android:layout_marginRight="@dimen/add_button_margin"
android:layout_marginTop="@dimen/standard_margin"
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index b38c5506..47d10ed6 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -206,5 +206,5 @@
<string name="advanced_settings">Paramètres avancés</string>
<string name="cancel_connection">Se déconnecter</string>
<string name="unknown_location">Site inconnu</string>
- <string name="splash_footer">Développé par : LEAP</string>
+ <string name="splash_footer">Développé par LEAP</string>
</resources>
diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml
index 057ced21..9b0539ab 100644
--- a/app/src/main/res/values-gl/strings.xml
+++ b/app/src/main/res/values-gl/strings.xml
@@ -111,7 +111,7 @@
<string name="require_root">Require permiso root</string>
<string name="show_experimental">Mostrar funcións experimentais</string>
<string name="hide_experimental">Agochar funcións experimentais</string>
- <string name="tethering_enabled_message">Asegúrate de ter antes activada a compartición da conexión en <![CDATA[1system settings1]]>.</string>
+ <string name="tethering_enabled_message">Asegúrate de ter antes activada a compartición da conexión en <![CDATA[<b>system settings</b>]]>.</string>
<string name="tethering_message">Comparte a túa VPN con outros dispositivos vía:</string>
<string name="tethering_wifi">Punto de acceso Wi-Fi</string>
<string name="tethering_usb">Compartición USB</string>
diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml
index 68005365..9d83ff49 100644
--- a/app/src/main/res/values-pt-rBR/strings.xml
+++ b/app/src/main/res/values-pt-rBR/strings.xml
@@ -114,7 +114,7 @@
<string name="show_experimental">Mostrar recursos experimentais</string>
<string name="hide_experimental">Esconder recursos experimentais</string>
<string name="experimental_features">Funcionalidades experimentais</string>
- <string name="tethering_enabled_message">Por favor tenha certeza de primeiro habilitar tethering nas &lt;![CDATA[&lt;b&gt;configurações de sistema&lt;/b&gt;]].</string>
+ <string name="tethering_enabled_message">Por favor tenha certeza de primeiro habilitar tethering nas <![CDATA[<b>configurações de sistema</b>]]>.</string>
<string name="tethering_message">Compartilhe sua VPN com outros dispositivos através de:</string>
<string name="tethering_wifi">Hotspot Wi-Fi</string>
<string name="tethering_usb">Tethering USB</string>
diff --git a/app/src/main/res/values-sw600dp/dimens.xml b/app/src/main/res/values-sw600dp/dimens.xml
index a046dac6..4c726da5 100644
--- a/app/src/main/res/values-sw600dp/dimens.xml
+++ b/app/src/main/res/values-sw600dp/dimens.xml
@@ -14,5 +14,7 @@
<!-- landscape dimens -->
<dimen name="footer_text_padding">20dp</dimen>
<dimen name="splash_text_top_padding">140dp</dimen>
+ <dimen name="mainbutton_padding">32dp</dimen>
+ <dimen name="donation_reminder_padding">24dp</dimen>
</resources> \ No newline at end of file
diff --git a/app/src/main/res/values-w820dp/dimens.xml b/app/src/main/res/values-w820dp/dimens.xml
index b38b10a6..822259ca 100644
--- a/app/src/main/res/values-w820dp/dimens.xml
+++ b/app/src/main/res/values-w820dp/dimens.xml
@@ -11,5 +11,7 @@
<!-- landscape dimens -->
<dimen name="footer_text_padding">12dp</dimen>
<dimen name="splash_text_top_padding">90dp</dimen>
+ <dimen name="mainbutton_padding">32dp</dimen>
+ <dimen name="donation_reminder_padding">24dp</dimen>
</resources>
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index c737d759..564f15f3 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -2,7 +2,7 @@
<resources>
<string name="retry">重试</string>
<string name="repository_url_text">源代码可在 https://0xacab.org/leap/bitmask_android 找到</string>
- <string name="leap_tracker">问题追踪器可在 https://0xacab.org/leap/bitmask_android 找到</string>
+ <string name="leap_tracker">问题追踪器可在 https://0xacab.org/leap/bitmask_android/issues 找到</string>
<string name="translation_project_text">我们鼓励并感谢诸位提供翻译。请在 https://www.transifex.com/projects/p/bitmask/ 参阅我们的 Transifex 项目</string>
<string name="switch_provider_menu_option">切换提供商</string>
<string name="info">信息</string>
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index ead4785e..3e33c72b 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -39,7 +39,7 @@
<color name="black_transparent">#20000000</color>
<color name="black_high_transparent">#05000000</color>
- <color name="colorEipFragmentFont">@color/black800</color>
+ <color name="colorEipFragmentFont">@color/black800_dark</color>
<!-- button text colors in Alerts etc. -->
<color name="color_font_btn">@color/black800</color>
<!-- pill style button text colors -->
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index 9ef6c3e0..f15fbcf9 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -8,7 +8,6 @@
<dimen name="stdpadding">8dp</dimen>
<dimen name="compact_padding">3dp</dimen>
<dimen name="standard_margin">8dp</dimen>
- <dimen name="mainbutton_padding">20dp</dimen>
<bool name="logSildersAlwaysVisible">false</bool>
<!-- landscape layout dimens -->
<dimen name="footer_text_padding">12dp</dimen>
@@ -46,4 +45,7 @@
<dimen name="toast_bottom_padding">20dp</dimen>
<dimen name="button_bevel">3dp</dimen>
<dimen name="button_radius">16dp</dimen>
+ <dimen name="mainbutton_padding">8dp</dimen>
+ <dimen name="donation_reminder_padding">8dp</dimen>
+
</resources> \ No newline at end of file
diff --git a/docker/android-ndk/Dockerfile b/docker/android-ndk/Dockerfile
index 8fe535f5..ffe189b3 100644
--- a/docker/android-ndk/Dockerfile
+++ b/docker/android-ndk/Dockerfile
@@ -24,7 +24,7 @@ RUN apt-get update -qq && \
# JNI build dependencies w/ 32-bit compatible C libs
RUN apt-get update -qq && \
apt-get -y install docker-ce docker-ce-cli make gcc swig file lib32stdc++6 lib32z1 \
- autoconf autogen automake autopoint autotools-dev gettext-base libtool patch pkg-config && \
+ autoconf autogen automake autopoint autotools-dev gettext-base libtool patch pkg-config po4a && \
apt-get clean && \
apt-get autoclean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
diff --git a/tor-android b/tor-android
-Subproject b7bf4551ff359e92e9023778715f39a4c7eb7cf
+Subproject c1c015af8d20ae44d045264c9b98dbf78caa433