mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-11 18:29:05 +01:00
Drop support for Android 4
new minSdk is 21
This commit is contained in:
@@ -11,7 +11,7 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 16
|
minSdkVersion 21
|
||||||
targetSdkVersion 31
|
targetSdkVersion 31
|
||||||
versionCode 10500
|
versionCode 10500
|
||||||
versionName "1.5.0"
|
versionName "1.5.0"
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import javax.annotation.Nullable;
|
|||||||
import javax.annotation.concurrent.GuardedBy;
|
import javax.annotation.concurrent.GuardedBy;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
import static org.briarproject.bramble.util.IoUtils.deleteFileOrDir;
|
import static org.briarproject.bramble.util.IoUtils.deleteFileOrDir;
|
||||||
@@ -105,15 +104,11 @@ class AndroidAccountManager extends AccountManagerImpl
|
|||||||
}
|
}
|
||||||
files.add(appContext.getFilesDir());
|
files.add(appContext.getFilesDir());
|
||||||
addIfNotNull(files, appContext.getExternalCacheDir());
|
addIfNotNull(files, appContext.getExternalCacheDir());
|
||||||
if (SDK_INT >= 19) {
|
for (File file : appContext.getExternalCacheDirs()) {
|
||||||
for (File file : appContext.getExternalCacheDirs()) {
|
addIfNotNull(files, file);
|
||||||
addIfNotNull(files, file);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (SDK_INT >= 21) {
|
for (File file : appContext.getExternalMediaDirs()) {
|
||||||
for (File file : appContext.getExternalMediaDirs()) {
|
addIfNotNull(files, file);
|
||||||
addIfNotNull(files, file);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Clear the cache directory but don't delete it
|
// Clear the cache directory but don't delete it
|
||||||
File cacheDir = appContext.getCacheDir();
|
File cacheDir = appContext.getCacheDir();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.briarproject.bramble.plugin.bluetooth;
|
package org.briarproject.bramble.plugin.bluetooth;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.bluetooth.BluetoothDevice;
|
import android.bluetooth.BluetoothDevice;
|
||||||
@@ -49,7 +50,6 @@ import static android.bluetooth.BluetoothAdapter.STATE_ON;
|
|||||||
import static android.bluetooth.BluetoothDevice.ACTION_FOUND;
|
import static android.bluetooth.BluetoothDevice.ACTION_FOUND;
|
||||||
import static android.bluetooth.BluetoothDevice.DEVICE_TYPE_LE;
|
import static android.bluetooth.BluetoothDevice.DEVICE_TYPE_LE;
|
||||||
import static android.bluetooth.BluetoothDevice.EXTRA_DEVICE;
|
import static android.bluetooth.BluetoothDevice.EXTRA_DEVICE;
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
|
||||||
import static java.util.Collections.shuffle;
|
import static java.util.Collections.shuffle;
|
||||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
@@ -60,6 +60,7 @@ import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
|
|||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
|
@SuppressLint("MissingPermission")
|
||||||
class AndroidBluetoothPlugin extends
|
class AndroidBluetoothPlugin extends
|
||||||
AbstractBluetoothPlugin<BluetoothSocket, BluetoothServerSocket> {
|
AbstractBluetoothPlugin<BluetoothSocket, BluetoothServerSocket> {
|
||||||
|
|
||||||
@@ -253,7 +254,7 @@ class AndroidBluetoothPlugin extends
|
|||||||
} else if (ACTION_FOUND.equals(action)) {
|
} else if (ACTION_FOUND.equals(action)) {
|
||||||
BluetoothDevice d = i.getParcelableExtra(EXTRA_DEVICE);
|
BluetoothDevice d = i.getParcelableExtra(EXTRA_DEVICE);
|
||||||
// Ignore Bluetooth LE devices
|
// Ignore Bluetooth LE devices
|
||||||
if (SDK_INT < 18 || d.getType() != DEVICE_TYPE_LE) {
|
if (d.getType() != DEVICE_TYPE_LE) {
|
||||||
String address = d.getAddress();
|
String address = d.getAddress();
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Discovered " +
|
LOG.info("Discovered " +
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package org.briarproject.bramble.plugin.tcp;
|
package org.briarproject.bramble.plugin.tcp;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.LinkAddress;
|
import android.net.LinkAddress;
|
||||||
@@ -37,7 +36,6 @@ import javax.net.SocketFactory;
|
|||||||
import static android.content.Context.CONNECTIVITY_SERVICE;
|
import static android.content.Context.CONNECTIVITY_SERVICE;
|
||||||
import static android.content.Context.WIFI_SERVICE;
|
import static android.content.Context.WIFI_SERVICE;
|
||||||
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
|
||||||
import static java.util.Collections.emptyList;
|
import static java.util.Collections.emptyList;
|
||||||
import static java.util.Collections.list;
|
import static java.util.Collections.list;
|
||||||
import static java.util.Collections.singletonList;
|
import static java.util.Collections.singletonList;
|
||||||
@@ -118,7 +116,7 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
|
|||||||
// If there's no wifi IPv4 address, we might be a client on an
|
// If there's no wifi IPv4 address, we might be a client on an
|
||||||
// IPv6-only wifi network. We can only detect this on API 21+
|
// IPv6-only wifi network. We can only detect this on API 21+
|
||||||
if (wifi == null) {
|
if (wifi == null) {
|
||||||
return SDK_INT >= 21 ? getWifiClientIpv6Address() : null;
|
return getWifiClientIpv6Address();
|
||||||
}
|
}
|
||||||
// Use the wifi IPv4 address to determine which interface's IPv6
|
// Use the wifi IPv4 address to determine which interface's IPv6
|
||||||
// address we should return (if the interface has a suitable address)
|
// address we should return (if the interface has a suitable address)
|
||||||
@@ -172,7 +170,6 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
|
|||||||
* Returns a link-local IPv6 address for the wifi client interface, or null
|
* Returns a link-local IPv6 address for the wifi client interface, or null
|
||||||
* if there's no such interface or it doesn't have a suitable address.
|
* if there's no such interface or it doesn't have a suitable address.
|
||||||
*/
|
*/
|
||||||
@TargetApi(21)
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private InetAddress getWifiClientIpv6Address() {
|
private InetAddress getWifiClientIpv6Address() {
|
||||||
// https://issuetracker.google.com/issues/175055271
|
// https://issuetracker.google.com/issues/175055271
|
||||||
@@ -234,7 +231,6 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
|
|||||||
// On API 21 and later, a socket that is not created with the wifi
|
// On API 21 and later, a socket that is not created with the wifi
|
||||||
// network's socket factory may try to connect via another network
|
// network's socket factory may try to connect via another network
|
||||||
private SocketFactory getSocketFactory() {
|
private SocketFactory getSocketFactory() {
|
||||||
if (SDK_INT < 21) return SocketFactory.getDefault();
|
|
||||||
// https://issuetracker.google.com/issues/175055271
|
// https://issuetracker.google.com/issues/175055271
|
||||||
try {
|
try {
|
||||||
for (Network net : connectivityManager.getAllNetworks()) {
|
for (Network net : connectivityManager.getAllNetworks()) {
|
||||||
@@ -302,7 +298,7 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
|
|||||||
Pair<InetAddress, Boolean> wifi = getWifiIpv4Address();
|
Pair<InetAddress, Boolean> wifi = getWifiIpv4Address();
|
||||||
// If there's no wifi IPv4 address, we might be a client on an
|
// If there's no wifi IPv4 address, we might be a client on an
|
||||||
// IPv6-only wifi network. We can only detect this on API 21+
|
// IPv6-only wifi network. We can only detect this on API 21+
|
||||||
if (wifi == null && SDK_INT >= 21) {
|
if (wifi == null) {
|
||||||
InetAddress ipv6 = getWifiClientIpv6Address();
|
InetAddress ipv6 = getWifiClientIpv6Address();
|
||||||
if (ipv6 != null) return new Pair<>(ipv6, false);
|
if (ipv6 != null) return new Pair<>(ipv6, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,8 +31,6 @@ import static android.provider.Settings.Secure.ANDROID_ID;
|
|||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class AndroidSecureRandomProvider extends UnixSecureRandomProvider {
|
class AndroidSecureRandomProvider extends UnixSecureRandomProvider {
|
||||||
|
|
||||||
private static final int SEED_LENGTH = 32;
|
|
||||||
|
|
||||||
private final Context appContext;
|
private final Context appContext;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -72,27 +70,6 @@ class AndroidSecureRandomProvider extends UnixSecureRandomProvider {
|
|||||||
// Silence strict mode
|
// Silence strict mode
|
||||||
StrictMode.ThreadPolicy tp = StrictMode.allowThreadDiskWrites();
|
StrictMode.ThreadPolicy tp = StrictMode.allowThreadDiskWrites();
|
||||||
super.writeSeed();
|
super.writeSeed();
|
||||||
if (SDK_INT <= 18) applyOpenSslFix();
|
|
||||||
StrictMode.setThreadPolicy(tp);
|
StrictMode.setThreadPolicy(tp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Based on https://android-developers.googleblog.com/2013/08/some-securerandom-thoughts.html
|
|
||||||
private void applyOpenSslFix() {
|
|
||||||
byte[] seed = new UnixSecureRandomSpi().engineGenerateSeed(
|
|
||||||
SEED_LENGTH);
|
|
||||||
try {
|
|
||||||
// Seed the OpenSSL PRNG
|
|
||||||
Class.forName("org.apache.harmony.xnet.provider.jsse.NativeCrypto")
|
|
||||||
.getMethod("RAND_seed", byte[].class)
|
|
||||||
.invoke(null, (Object) seed);
|
|
||||||
// Mix the output of the Linux PRNG into the OpenSSL PRNG
|
|
||||||
int bytesRead = (Integer) Class.forName(
|
|
||||||
"org.apache.harmony.xnet.provider.jsse.NativeCrypto")
|
|
||||||
.getMethod("RAND_load_file", String.class, long.class)
|
|
||||||
.invoke(null, "/dev/urandom", 1024);
|
|
||||||
if (bytesRead != 1024) throw new IOException();
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new SecurityException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,14 +11,10 @@ import org.briarproject.bramble.api.Pair;
|
|||||||
import org.briarproject.nullsafety.NotNullByDefault;
|
import org.briarproject.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Scanner;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
@@ -29,7 +25,6 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
|||||||
import static android.os.Build.VERSION.SDK_INT;
|
import static android.os.Build.VERSION.SDK_INT;
|
||||||
import static android.os.Process.myPid;
|
import static android.os.Process.myPid;
|
||||||
import static android.os.Process.myUid;
|
import static android.os.Process.myUid;
|
||||||
import static java.lang.Runtime.getRuntime;
|
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
import static org.briarproject.nullsafety.NullSafety.requireNonNull;
|
import static org.briarproject.nullsafety.NullSafety.requireNonNull;
|
||||||
|
|
||||||
@@ -43,14 +38,7 @@ public class AndroidUtils {
|
|||||||
private static final String STORED_LOGCAT = "dev-logcat";
|
private static final String STORED_LOGCAT = "dev-logcat";
|
||||||
|
|
||||||
public static Collection<String> getSupportedArchitectures() {
|
public static Collection<String> getSupportedArchitectures() {
|
||||||
List<String> abis = new ArrayList<>();
|
return asList(Build.SUPPORTED_ABIS);
|
||||||
if (SDK_INT >= 21) {
|
|
||||||
abis.addAll(asList(Build.SUPPORTED_ABIS));
|
|
||||||
} else {
|
|
||||||
abis.add(Build.CPU_ABI);
|
|
||||||
if (Build.CPU_ABI2 != null) abis.add(Build.CPU_ABI2);
|
|
||||||
}
|
|
||||||
return abis;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean hasBtConnectPermission(Context ctx) {
|
public static boolean hasBtConnectPermission(Context ctx) {
|
||||||
@@ -136,19 +124,6 @@ public class AndroidUtils {
|
|||||||
return new String[] {"image/jpeg", "image/png", "image/gif"};
|
return new String[] {"image/jpeg", "image/png", "image/gif"};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public static String getSystemProperty(String propName) {
|
|
||||||
try {
|
|
||||||
Process p = getRuntime().exec("getprop " + propName);
|
|
||||||
Scanner s = new Scanner(p.getInputStream());
|
|
||||||
String line = s.nextLine();
|
|
||||||
s.close();
|
|
||||||
return line;
|
|
||||||
} catch (SecurityException | IOException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isUiThread() {
|
public static boolean isUiThread() {
|
||||||
return Looper.myLooper() == Looper.getMainLooper();
|
return Looper.myLooper() == Looper.getMainLooper();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 16
|
minSdkVersion 21
|
||||||
targetSdkVersion 31
|
targetSdkVersion 31
|
||||||
versionCode 10500
|
versionCode 10500
|
||||||
versionName "1.5.0"
|
versionName "1.5.0"
|
||||||
@@ -62,7 +62,6 @@ android {
|
|||||||
productFlavors {
|
productFlavors {
|
||||||
screenshot {
|
screenshot {
|
||||||
dimension "version"
|
dimension "version"
|
||||||
minSdkVersion 21
|
|
||||||
applicationIdSuffix ".screenshot" // = org.briarproject.briar.android.screenshot.debug
|
applicationIdSuffix ".screenshot" // = org.briarproject.briar.android.screenshot.debug
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt', 'proguard-test.txt'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt', 'proguard-test.txt'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,11 +99,6 @@
|
|||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:label="@string/app_name" />
|
android:label="@string/app_name" />
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name="org.briarproject.briar.android.splash.ExpiredOldAndroidActivity"
|
|
||||||
android:exported="false"
|
|
||||||
android:label="@string/app_name" />
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="org.briarproject.briar.android.login.StartupActivity"
|
android:name="org.briarproject.briar.android.login.StartupActivity"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
|
|||||||
@@ -294,10 +294,8 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
b.setOngoing(true);
|
b.setOngoing(true);
|
||||||
Intent i = new Intent(appContext, SplashScreenActivity.class);
|
Intent i = new Intent(appContext, SplashScreenActivity.class);
|
||||||
b.setContentIntent(getActivity(appContext, 0, i, getImmutableFlags(0)));
|
b.setContentIntent(getActivity(appContext, 0, i, getImmutableFlags(0)));
|
||||||
if (SDK_INT >= 21) {
|
b.setCategory(CATEGORY_SERVICE);
|
||||||
b.setCategory(CATEGORY_SERVICE);
|
b.setVisibility(VISIBILITY_SECRET);
|
||||||
b.setVisibility(VISIBILITY_SECRET);
|
|
||||||
}
|
|
||||||
b.setPriority(PRIORITY_MIN);
|
b.setPriority(PRIORITY_MIN);
|
||||||
return b.build();
|
return b.build();
|
||||||
}
|
}
|
||||||
@@ -773,8 +771,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
i.setAction(ACTION_STOP_HOTSPOT);
|
i.setAction(ACTION_STOP_HOTSPOT);
|
||||||
PendingIntent actionIntent =
|
PendingIntent actionIntent =
|
||||||
getActivity(appContext, 0, i, getImmutableFlags(0));
|
getActivity(appContext, 0, i, getImmutableFlags(0));
|
||||||
int icon = SDK_INT >= 21 ? R.drawable.ic_portable_wifi_off : 0;
|
b.addAction(R.drawable.ic_portable_wifi_off, actionTitle, actionIntent);
|
||||||
b.addAction(icon, actionTitle, actionIntent);
|
|
||||||
notificationManager.notify(HOTSPOT_NOTIFICATION_ID, b.build());
|
notificationManager.notify(HOTSPOT_NOTIFICATION_ID, b.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ public class AppModule {
|
|||||||
public Collection<SimplexPluginFactory> getSimplexFactories() {
|
public Collection<SimplexPluginFactory> getSimplexFactories() {
|
||||||
List<SimplexPluginFactory> simplex = new ArrayList<>();
|
List<SimplexPluginFactory> simplex = new ArrayList<>();
|
||||||
simplex.add(mailbox);
|
simplex.add(mailbox);
|
||||||
if (SDK_INT >= 19) simplex.add(drive);
|
simplex.add(drive);
|
||||||
return simplex;
|
return simplex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,16 +56,8 @@ public class Localizer {
|
|||||||
// Get Locale from BCP-47 tag
|
// Get Locale from BCP-47 tag
|
||||||
@Nullable
|
@Nullable
|
||||||
public static Locale getLocaleFromTag(String tag) {
|
public static Locale getLocaleFromTag(String tag) {
|
||||||
if (tag.equals("default"))
|
if (tag.equals("default")) return null;
|
||||||
return null;
|
return Locale.forLanguageTag(tag);
|
||||||
if (SDK_INT >= 21) {
|
|
||||||
return Locale.forLanguageTag(tag);
|
|
||||||
}
|
|
||||||
if (tag.contains("-")) {
|
|
||||||
String[] langArray = tag.split("-");
|
|
||||||
return new Locale(langArray[0], langArray[1]);
|
|
||||||
} else
|
|
||||||
return new Locale(tag);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -94,12 +86,8 @@ public class Localizer {
|
|||||||
if (locale.equals(currentLocale))
|
if (locale.equals(currentLocale))
|
||||||
return context;
|
return context;
|
||||||
Locale.setDefault(locale);
|
Locale.setDefault(locale);
|
||||||
if (SDK_INT >= 17) {
|
conf.setLocale(locale);
|
||||||
conf.setLocale(locale);
|
context = context.createConfigurationContext(conf);
|
||||||
context = context.createConfigurationContext(conf);
|
|
||||||
} else
|
|
||||||
conf.locale = locale;
|
|
||||||
//noinspection deprecation
|
|
||||||
res.updateConfiguration(conf, res.getDisplayMetrics());
|
res.updateConfiguration(conf, res.getDisplayMetrics());
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ package org.briarproject.briar.android;
|
|||||||
|
|
||||||
import org.briarproject.briar.BuildConfig;
|
import org.briarproject.briar.BuildConfig;
|
||||||
|
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
|
||||||
import static java.util.concurrent.TimeUnit.DAYS;
|
import static java.util.concurrent.TimeUnit.DAYS;
|
||||||
|
import static org.briarproject.briar.BuildConfig.BuildTimestamp;
|
||||||
|
|
||||||
public interface TestingConstants {
|
public interface TestingConstants {
|
||||||
|
|
||||||
@@ -20,15 +20,9 @@ public interface TestingConstants {
|
|||||||
*/
|
*/
|
||||||
boolean PREVENT_SCREENSHOTS = !IS_DEBUG_BUILD;
|
boolean PREVENT_SCREENSHOTS = !IS_DEBUG_BUILD;
|
||||||
|
|
||||||
boolean IS_OLD_ANDROID = SDK_INT <= 19;
|
|
||||||
long OLD_ANDROID_WARN_DATE = 1659225600_000L; // 2022-07-31
|
|
||||||
long OLD_ANDROID_EXPIRY_DATE = 1675123200_000L; // 2023-01-31
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Debug builds expire after 90 days. Release builds running on Android 4
|
* Debug builds expire after 90 days.
|
||||||
* expire at a set date, otherwise they expire after 292 million years.
|
|
||||||
*/
|
*/
|
||||||
long EXPIRY_DATE = IS_DEBUG_BUILD ?
|
long EXPIRY_DATE = IS_DEBUG_BUILD ?
|
||||||
BuildConfig.BuildTimestamp + DAYS.toMillis(90)
|
BuildTimestamp + DAYS.toMillis(90) : Long.MAX_VALUE;
|
||||||
: (IS_OLD_ANDROID ? OLD_ANDROID_EXPIRY_DATE : Long.MAX_VALUE);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_KEYGU
|
|||||||
import static org.briarproject.briar.android.util.UiUtils.hasKeyguardLock;
|
import static org.briarproject.briar.android.util.UiUtils.hasKeyguardLock;
|
||||||
import static org.briarproject.briar.android.util.UiUtils.hasUsableFingerprint;
|
import static org.briarproject.briar.android.util.UiUtils.hasUsableFingerprint;
|
||||||
|
|
||||||
@RequiresApi(21)
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
public class UnlockActivity extends BaseActivity {
|
public class UnlockActivity extends BaseActivity {
|
||||||
|
|||||||
@@ -81,7 +81,6 @@ import org.briarproject.briar.android.sharing.ShareBlogFragment;
|
|||||||
import org.briarproject.briar.android.sharing.ShareForumActivity;
|
import org.briarproject.briar.android.sharing.ShareForumActivity;
|
||||||
import org.briarproject.briar.android.sharing.ShareForumFragment;
|
import org.briarproject.briar.android.sharing.ShareForumFragment;
|
||||||
import org.briarproject.briar.android.sharing.SharingModule;
|
import org.briarproject.briar.android.sharing.SharingModule;
|
||||||
import org.briarproject.briar.android.splash.ExpiredOldAndroidActivity;
|
|
||||||
import org.briarproject.briar.android.splash.SplashScreenActivity;
|
import org.briarproject.briar.android.splash.SplashScreenActivity;
|
||||||
import org.briarproject.briar.android.test.TestDataActivity;
|
import org.briarproject.briar.android.test.TestDataActivity;
|
||||||
|
|
||||||
@@ -184,8 +183,6 @@ public interface ActivityComponent {
|
|||||||
|
|
||||||
void inject(RemovableDriveActivity activity);
|
void inject(RemovableDriveActivity activity);
|
||||||
|
|
||||||
void inject(ExpiredOldAndroidActivity activity);
|
|
||||||
|
|
||||||
// Fragments
|
// Fragments
|
||||||
|
|
||||||
void inject(SetupFragment fragment);
|
void inject(SetupFragment fragment);
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import java.util.logging.Logger;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
import androidx.appcompat.app.ActionBar;
|
import androidx.appcompat.app.ActionBar;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
@@ -105,7 +104,7 @@ public abstract class BriarActivity extends BaseActivity {
|
|||||||
LOG.info("Not signed in, launching StartupActivity");
|
LOG.info("Not signed in, launching StartupActivity");
|
||||||
Intent i = new Intent(this, StartupActivity.class);
|
Intent i = new Intent(this, StartupActivity.class);
|
||||||
startActivityForResult(i, REQUEST_PASSWORD);
|
startActivityForResult(i, REQUEST_PASSWORD);
|
||||||
} else if (SDK_INT >= 21 && lockManager.isLocked() && !isFinishing()) {
|
} else if (lockManager.isLocked() && !isFinishing()) {
|
||||||
// Also check that the activity isn't finishing already.
|
// Also check that the activity isn't finishing already.
|
||||||
// This is possible if we finished in onActivityResult().
|
// This is possible if we finished in onActivityResult().
|
||||||
// Launching another UnlockActivity would cause a loop.
|
// Launching another UnlockActivity would cause a loop.
|
||||||
@@ -135,8 +134,7 @@ public abstract class BriarActivity extends BaseActivity {
|
|||||||
* @param exitTransition used to move views out when starting a <b>new</b> activity.
|
* @param exitTransition used to move views out when starting a <b>new</b> activity.
|
||||||
* @param returnTransition used when window is closing, because the activity is finishing.
|
* @param returnTransition used when window is closing, because the activity is finishing.
|
||||||
*/
|
*/
|
||||||
@RequiresApi(api = 21)
|
protected void setSceneTransitionAnimation(
|
||||||
public void setSceneTransitionAnimation(
|
|
||||||
@Nullable Transition enterTransition,
|
@Nullable Transition enterTransition,
|
||||||
@Nullable Transition exitTransition,
|
@Nullable Transition exitTransition,
|
||||||
@Nullable Transition returnTransition) {
|
@Nullable Transition returnTransition) {
|
||||||
@@ -232,8 +230,7 @@ public abstract class BriarActivity extends BaseActivity {
|
|||||||
|
|
||||||
@Wakeful
|
@Wakeful
|
||||||
private void finishAndExit() {
|
private void finishAndExit() {
|
||||||
if (SDK_INT >= 21) finishAndRemoveTask();
|
finishAndRemoveTask();
|
||||||
else supportFinishAfterTransition();
|
|
||||||
LOG.info("Exiting");
|
LOG.info("Exiting");
|
||||||
BriarApplication app = (BriarApplication) getApplication();
|
BriarApplication app = (BriarApplication) getApplication();
|
||||||
if (!app.isInstrumentationTest()) System.exit(0);
|
if (!app.isInstrumentationTest()) System.exit(0);
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import androidx.annotation.UiThread;
|
|||||||
import androidx.core.view.ViewCompat;
|
import androidx.core.view.ViewCompat;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
|
||||||
import static android.view.View.GONE;
|
import static android.view.View.GONE;
|
||||||
import static android.view.View.VISIBLE;
|
import static android.view.View.VISIBLE;
|
||||||
import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
|
import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
|
||||||
@@ -134,12 +133,6 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
|||||||
} else {
|
} else {
|
||||||
reblogger.setVisibility(GONE);
|
reblogger.setVisibility(GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply Android 4 padding fix after setting up author/reblogger views
|
|
||||||
if (SDK_INT < 21) {
|
|
||||||
reblogger.setPadding(padding, padding, padding, padding);
|
|
||||||
author.setPadding(padding, padding, padding, padding);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onBindComment(BlogCommentItem item, boolean authorClickable) {
|
private void onBindComment(BlogCommentItem item, boolean authorClickable) {
|
||||||
|
|||||||
@@ -27,11 +27,9 @@ import javax.annotation.Nullable;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import androidx.activity.result.ActivityResultLauncher;
|
import androidx.activity.result.ActivityResultLauncher;
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
|
||||||
import static android.view.View.GONE;
|
import static android.view.View.GONE;
|
||||||
import static android.view.View.VISIBLE;
|
import static android.view.View.VISIBLE;
|
||||||
import static android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
|
import static android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
|
||||||
@@ -52,7 +50,6 @@ public class RssFeedImportFragment extends BaseFragment {
|
|||||||
private Button importButton;
|
private Button importButton;
|
||||||
private ProgressBar progressBar;
|
private ProgressBar progressBar;
|
||||||
|
|
||||||
@RequiresApi(19)
|
|
||||||
private final ActivityResultLauncher<String[]> docLauncher =
|
private final ActivityResultLauncher<String[]> docLauncher =
|
||||||
registerForActivityResult(new OpenDocumentAdvanced(),
|
registerForActivityResult(new OpenDocumentAdvanced(),
|
||||||
this::onFileChosen);
|
this::onFileChosen);
|
||||||
@@ -74,7 +71,7 @@ public class RssFeedImportFragment extends BaseFragment {
|
|||||||
@Nullable ViewGroup container,
|
@Nullable ViewGroup container,
|
||||||
@Nullable Bundle savedInstanceState) {
|
@Nullable Bundle savedInstanceState) {
|
||||||
requireActivity().setTitle(getString(R.string.blogs_rss_feeds_import));
|
requireActivity().setTitle(getString(R.string.blogs_rss_feeds_import));
|
||||||
if (SDK_INT >= 19) setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
View v = inflater.inflate(R.layout.fragment_rss_feed_import,
|
View v = inflater.inflate(R.layout.fragment_rss_feed_import,
|
||||||
container, false);
|
container, false);
|
||||||
|
|
||||||
@@ -117,15 +114,13 @@ public class RssFeedImportFragment extends BaseFragment {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
if (SDK_INT >= 19) {
|
inflater.inflate(R.menu.rss_feed_import_actions, menu);
|
||||||
inflater.inflate(R.menu.rss_feed_import_actions, menu);
|
|
||||||
}
|
|
||||||
super.onCreateOptionsMenu(menu, inflater);
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
if (item.getItemId() == R.id.action_import_file && SDK_INT >= 19) {
|
if (item.getItemId() == R.id.action_import_file) {
|
||||||
launchActivityToOpenFile(requireContext(), docLauncher,
|
launchActivityToOpenFile(requireContext(), docLauncher,
|
||||||
contentLauncher, "*/*");
|
contentLauncher, "*/*");
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener
|
|||||||
import org.briarproject.briar.android.introduction.IntroductionActivity;
|
import org.briarproject.briar.android.introduction.IntroductionActivity;
|
||||||
import org.briarproject.briar.android.privategroup.conversation.GroupActivity;
|
import org.briarproject.briar.android.privategroup.conversation.GroupActivity;
|
||||||
import org.briarproject.briar.android.removabledrive.RemovableDriveActivity;
|
import org.briarproject.briar.android.removabledrive.RemovableDriveActivity;
|
||||||
import org.briarproject.briar.android.util.ActivityLaunchers.GetImageAdvanced;
|
|
||||||
import org.briarproject.briar.android.util.ActivityLaunchers.GetMultipleImagesAdvanced;
|
import org.briarproject.briar.android.util.ActivityLaunchers.GetMultipleImagesAdvanced;
|
||||||
import org.briarproject.briar.android.util.ActivityLaunchers.OpenMultipleImageDocumentsAdvanced;
|
import org.briarproject.briar.android.util.ActivityLaunchers.OpenMultipleImageDocumentsAdvanced;
|
||||||
import org.briarproject.briar.android.util.BriarSnackbarBuilder;
|
import org.briarproject.briar.android.util.BriarSnackbarBuilder;
|
||||||
@@ -122,13 +121,11 @@ import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;
|
|||||||
import de.hdodenhof.circleimageview.CircleImageView;
|
import de.hdodenhof.circleimageview.CircleImageView;
|
||||||
import uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt;
|
import uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt;
|
||||||
|
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
|
||||||
import static android.view.Gravity.RIGHT;
|
import static android.view.Gravity.RIGHT;
|
||||||
import static android.widget.Toast.LENGTH_SHORT;
|
import static android.widget.Toast.LENGTH_SHORT;
|
||||||
import static androidx.core.app.ActivityOptionsCompat.makeSceneTransitionAnimation;
|
import static androidx.core.app.ActivityOptionsCompat.makeSceneTransitionAnimation;
|
||||||
import static androidx.lifecycle.Lifecycle.State.STARTED;
|
import static androidx.lifecycle.Lifecycle.State.STARTED;
|
||||||
import static androidx.recyclerview.widget.SortedList.INVALID_POSITION;
|
import static androidx.recyclerview.widget.SortedList.INVALID_POSITION;
|
||||||
import static java.util.Collections.singletonList;
|
|
||||||
import static java.util.Collections.sort;
|
import static java.util.Collections.sort;
|
||||||
import static java.util.Objects.requireNonNull;
|
import static java.util.Objects.requireNonNull;
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
@@ -200,18 +197,13 @@ public class ConversationActivity extends BriarActivity
|
|||||||
requireNonNull(name);
|
requireNonNull(name);
|
||||||
loadMessages();
|
loadMessages();
|
||||||
};
|
};
|
||||||
@Nullable
|
|
||||||
private final ActivityResultLauncher<String[]> docLauncher = SDK_INT >= 19 ?
|
private final ActivityResultLauncher<String[]> docLauncher =
|
||||||
registerForActivityResult(new OpenMultipleImageDocumentsAdvanced(),
|
registerForActivityResult(new OpenMultipleImageDocumentsAdvanced(),
|
||||||
this::onImagesChosen) :
|
this::onImagesChosen);
|
||||||
null;
|
|
||||||
private final ActivityResultLauncher<String> contentLauncher =
|
private final ActivityResultLauncher<String> contentLauncher =
|
||||||
SDK_INT >= 18 ?
|
registerForActivityResult(new GetMultipleImagesAdvanced(),
|
||||||
registerForActivityResult(new GetMultipleImagesAdvanced(),
|
this::onImagesChosen);
|
||||||
this::onImagesChosen) :
|
|
||||||
registerForActivityResult(new GetImageAdvanced(), uri -> {
|
|
||||||
if (uri != null) onImagesChosen(singletonList(uri));
|
|
||||||
});
|
|
||||||
|
|
||||||
private AttachmentRetriever attachmentRetriever;
|
private AttachmentRetriever attachmentRetriever;
|
||||||
private ConversationViewModel viewModel;
|
private ConversationViewModel viewModel;
|
||||||
@@ -242,13 +234,11 @@ public class ConversationActivity extends BriarActivity
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable Bundle state) {
|
public void onCreate(@Nullable Bundle state) {
|
||||||
if (SDK_INT >= 21) {
|
// Spurious lint warning - using END causes a crash
|
||||||
// Spurious lint warning - using END causes a crash
|
@SuppressLint("RtlHardcoded")
|
||||||
@SuppressLint("RtlHardcoded")
|
Transition slide = new Slide(RIGHT);
|
||||||
Transition slide = new Slide(RIGHT);
|
slide.setDuration(TRANSITION_DURATION_MS);
|
||||||
slide.setDuration(TRANSITION_DURATION_MS);
|
setSceneTransitionAnimation(slide, null, slide);
|
||||||
setSceneTransitionAnimation(slide, null, slide);
|
|
||||||
}
|
|
||||||
super.onCreate(state);
|
super.onCreate(state);
|
||||||
|
|
||||||
Intent i = getIntent();
|
Intent i = getIntent();
|
||||||
@@ -389,10 +379,6 @@ public class ConversationActivity extends BriarActivity
|
|||||||
this::showIntroductionOnboarding);
|
this::showIntroductionOnboarding);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// Transfer Data feature only supported on API 19+
|
|
||||||
if (SDK_INT >= 19) {
|
|
||||||
menu.findItem(R.id.action_transfer_data).setVisible(true);
|
|
||||||
}
|
|
||||||
// enable alias and bluetooth action once available
|
// enable alias and bluetooth action once available
|
||||||
observeOnce(viewModel.getContactItem(), this, contact -> {
|
observeOnce(viewModel.getContactItem(), this, contact -> {
|
||||||
menu.findItem(R.id.action_set_alias).setEnabled(true);
|
menu.findItem(R.id.action_set_alias).setEnabled(true);
|
||||||
@@ -434,11 +420,9 @@ public class ConversationActivity extends BriarActivity
|
|||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
return true;
|
return true;
|
||||||
} else if (itemId == R.id.action_transfer_data) {
|
} else if (itemId == R.id.action_transfer_data) {
|
||||||
if (SDK_INT >= 19) {
|
Intent intent = new Intent(this, RemovableDriveActivity.class);
|
||||||
Intent intent = new Intent(this, RemovableDriveActivity.class);
|
intent.putExtra(CONTACT_ID, contactId.getInt());
|
||||||
intent.putExtra(CONTACT_ID, contactId.getInt());
|
startActivity(intent);
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
} else if (itemId == R.id.action_delete_all_messages) {
|
} else if (itemId == R.id.action_delete_all_messages) {
|
||||||
askToDeleteAllMessages();
|
askToDeleteAllMessages();
|
||||||
@@ -955,14 +939,10 @@ public class ConversationActivity extends BriarActivity
|
|||||||
|
|
||||||
private void showImageOnboarding(Boolean show) {
|
private void showImageOnboarding(Boolean show) {
|
||||||
if (!show) return;
|
if (!show) return;
|
||||||
if (SDK_INT >= 21) {
|
// show onboarding only after the enter transition has ended
|
||||||
// show onboarding only after the enter transition has ended
|
// otherwise the tap target animation won't play
|
||||||
// otherwise the tap target animation won't play
|
textInputView.postDelayed(this::showImageOnboarding,
|
||||||
textInputView.postDelayed(this::showImageOnboarding,
|
TRANSITION_DURATION_MS + ONBOARDING_DELAY_MS);
|
||||||
TRANSITION_DURATION_MS + ONBOARDING_DELAY_MS);
|
|
||||||
} else {
|
|
||||||
showImageOnboarding();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showImageOnboarding() {
|
private void showImageOnboarding() {
|
||||||
@@ -973,14 +953,10 @@ public class ConversationActivity extends BriarActivity
|
|||||||
|
|
||||||
private void showIntroductionOnboarding(@Nullable Boolean show) {
|
private void showIntroductionOnboarding(@Nullable Boolean show) {
|
||||||
if (show == null || !show) return;
|
if (show == null || !show) return;
|
||||||
if (SDK_INT >= 21) {
|
// show onboarding only after the enter transition has ended
|
||||||
// show onboarding only after the enter transition has ended
|
// otherwise the tap target animation won't play
|
||||||
// otherwise the tap target animation won't play
|
textInputView.postDelayed(this::showIntroductionOnboarding,
|
||||||
textInputView.postDelayed(this::showIntroductionOnboarding,
|
TRANSITION_DURATION_MS + ONBOARDING_DELAY_MS);
|
||||||
TRANSITION_DURATION_MS + ONBOARDING_DELAY_MS);
|
|
||||||
} else {
|
|
||||||
showIntroductionOnboarding();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showIntroductionOnboarding() {
|
private void showIntroductionOnboarding() {
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import org.briarproject.briar.android.util.BriarSnackbarBuilder;
|
|||||||
import org.briarproject.briar.android.view.PullDownLayout;
|
import org.briarproject.briar.android.view.PullDownLayout;
|
||||||
import org.briarproject.nullsafety.MethodsNotNullByDefault;
|
import org.briarproject.nullsafety.MethodsNotNullByDefault;
|
||||||
import org.briarproject.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.nullsafety.ParametersNotNullByDefault;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -41,13 +42,11 @@ import androidx.viewpager2.adapter.FragmentStateAdapter;
|
|||||||
import androidx.viewpager2.widget.ViewPager2;
|
import androidx.viewpager2.widget.ViewPager2;
|
||||||
|
|
||||||
import static android.graphics.Color.TRANSPARENT;
|
import static android.graphics.Color.TRANSPARENT;
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
|
||||||
import static android.view.View.GONE;
|
import static android.view.View.GONE;
|
||||||
import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
|
import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
|
||||||
import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
|
import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
|
||||||
import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
|
import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
|
||||||
import static android.view.View.VISIBLE;
|
import static android.view.View.VISIBLE;
|
||||||
import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
|
|
||||||
import static com.google.android.material.snackbar.Snackbar.LENGTH_LONG;
|
import static com.google.android.material.snackbar.Snackbar.LENGTH_LONG;
|
||||||
import static java.util.Objects.requireNonNull;
|
import static java.util.Objects.requireNonNull;
|
||||||
import static org.briarproject.briar.android.util.UiUtils.formatDateAbsolute;
|
import static org.briarproject.briar.android.util.UiUtils.formatDateAbsolute;
|
||||||
@@ -77,11 +76,9 @@ public class ImageActivity extends BriarActivity
|
|||||||
private List<AttachmentItem> attachments;
|
private List<AttachmentItem> attachments;
|
||||||
private MessageId conversationMessageId;
|
private MessageId conversationMessageId;
|
||||||
|
|
||||||
@Nullable
|
private final ActivityResultLauncher<String> launcher =
|
||||||
private final ActivityResultLauncher<String> launcher = SDK_INT >= 19 ?
|
|
||||||
registerForActivityResult(new CreateDocumentAdvanced(),
|
registerForActivityResult(new CreateDocumentAdvanced(),
|
||||||
this::onImageUriSelected) :
|
this::onImageUriSelected);
|
||||||
null;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void injectActivity(ActivityComponent component) {
|
public void injectActivity(ActivityComponent component) {
|
||||||
@@ -97,10 +94,8 @@ public class ImageActivity extends BriarActivity
|
|||||||
// Transitions
|
// Transitions
|
||||||
if (state == null) supportPostponeEnterTransition();
|
if (state == null) supportPostponeEnterTransition();
|
||||||
Window window = getWindow();
|
Window window = getWindow();
|
||||||
if (SDK_INT >= 21) {
|
Transition transition = new Fade();
|
||||||
Transition transition = new Fade();
|
setSceneTransitionAnimation(transition, null, transition);
|
||||||
setSceneTransitionAnimation(transition, null, transition);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Intent Extras
|
// Intent Extras
|
||||||
Intent i = getIntent();
|
Intent i = getIntent();
|
||||||
@@ -124,12 +119,7 @@ public class ImageActivity extends BriarActivity
|
|||||||
layout.getViewTreeObserver().addOnGlobalLayoutListener(this);
|
layout.getViewTreeObserver().addOnGlobalLayoutListener(this);
|
||||||
|
|
||||||
// Status Bar
|
// Status Bar
|
||||||
if (SDK_INT >= 21) {
|
window.setStatusBarColor(TRANSPARENT);
|
||||||
window.setStatusBarColor(TRANSPARENT);
|
|
||||||
} else if (SDK_INT >= 19) {
|
|
||||||
// we can't make the status bar transparent, but translucent
|
|
||||||
window.addFlags(FLAG_TRANSLUCENT_STATUS);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Toolbar
|
// Toolbar
|
||||||
appBarLayout = findViewById(R.id.appBarLayout);
|
appBarLayout = findViewById(R.id.appBarLayout);
|
||||||
@@ -257,16 +247,12 @@ public class ImageActivity extends BriarActivity
|
|||||||
|
|
||||||
private void showSaveImageDialog() {
|
private void showSaveImageDialog() {
|
||||||
OnClickListener okListener = (dialog, which) -> {
|
OnClickListener okListener = (dialog, which) -> {
|
||||||
if (SDK_INT >= 19) {
|
String name = viewModel.getFileName() + "." +
|
||||||
String name = viewModel.getFileName() + "." +
|
getVisibleAttachment().getExtension();
|
||||||
getVisibleAttachment().getExtension();
|
try {
|
||||||
try {
|
launcher.launch(name);
|
||||||
requireNonNull(launcher).launch(name);
|
} catch (ActivityNotFoundException e) {
|
||||||
} catch (ActivityNotFoundException e) {
|
viewModel.onSaveImageError();
|
||||||
viewModel.onSaveImageError();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
viewModel.saveImage(getVisibleAttachment());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Builder builder = new Builder(this, R.style.BriarDialogTheme);
|
Builder builder = new Builder(this, R.style.BriarDialogTheme);
|
||||||
@@ -295,7 +281,7 @@ public class ImageActivity extends BriarActivity
|
|||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
AttachmentItem getVisibleAttachment() {
|
private AttachmentItem getVisibleAttachment() {
|
||||||
return attachments.get(viewPager.getCurrentItem());
|
return attachments.get(viewPager.getCurrentItem());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,6 +293,7 @@ public class ImageActivity extends BriarActivity
|
|||||||
super(ImageActivity.this);
|
super(ImageActivity.this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Fragment createFragment(int position) {
|
public Fragment createFragment(int position) {
|
||||||
Fragment f = ImageFragment.newInstance(
|
Fragment f = ImageFragment.newInstance(
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ import androidx.fragment.app.Fragment;
|
|||||||
import androidx.lifecycle.LifecycleOwner;
|
import androidx.lifecycle.LifecycleOwner;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
|
||||||
import static android.widget.ImageView.ScaleType.FIT_START;
|
import static android.widget.ImageView.ScaleType.FIT_START;
|
||||||
import static com.bumptech.glide.load.engine.DiskCacheStrategy.NONE;
|
import static com.bumptech.glide.load.engine.DiskCacheStrategy.NONE;
|
||||||
import static org.briarproject.briar.android.attachment.AttachmentItem.State.AVAILABLE;
|
import static org.briarproject.briar.android.attachment.AttachmentItem.State.AVAILABLE;
|
||||||
@@ -150,7 +149,7 @@ public class ImageFragment extends Fragment
|
|||||||
public boolean onResourceReady(Drawable resource, Object model,
|
public boolean onResourceReady(Drawable resource, Object model,
|
||||||
Target<Drawable> target, DataSource dataSource,
|
Target<Drawable> target, DataSource dataSource,
|
||||||
boolean isFirstResource) {
|
boolean isFirstResource) {
|
||||||
if (SDK_INT >= 21 && !(resource instanceof Animatable)) {
|
if (!(resource instanceof Animatable)) {
|
||||||
// set transition name only when not animatable,
|
// set transition name only when not animatable,
|
||||||
// because the animation won't start otherwise
|
// because the animation won't start otherwise
|
||||||
photoView.setTransitionName(
|
photoView.setTransitionName(
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import androidx.annotation.DrawableRes;
|
|||||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||||
import androidx.recyclerview.widget.StaggeredGridLayoutManager.LayoutParams;
|
import androidx.recyclerview.widget.StaggeredGridLayoutManager.LayoutParams;
|
||||||
|
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
|
||||||
import static android.widget.ImageView.ScaleType.CENTER_CROP;
|
import static android.widget.ImageView.ScaleType.CENTER_CROP;
|
||||||
import static android.widget.ImageView.ScaleType.FIT_CENTER;
|
import static android.widget.ImageView.ScaleType.FIT_CENTER;
|
||||||
import static com.bumptech.glide.load.engine.DiskCacheStrategy.NONE;
|
import static com.bumptech.glide.load.engine.DiskCacheStrategy.NONE;
|
||||||
@@ -58,10 +57,8 @@ class ImageViewHolder extends ViewHolder {
|
|||||||
loadImage(attachment, r);
|
loadImage(attachment, r);
|
||||||
imageView.setScaleType(CENTER_CROP);
|
imageView.setScaleType(CENTER_CROP);
|
||||||
}
|
}
|
||||||
if (SDK_INT >= 21) {
|
imageView.setTransitionName(
|
||||||
imageView.setTransitionName(
|
attachment.getTransitionName(conversationItemId));
|
||||||
attachment.getTransitionName(conversationItemId));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setImageViewDimensions(AttachmentItem a, boolean single,
|
private void setImageViewDimensions(AttachmentItem a, boolean single,
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
package org.briarproject.briar.android.forum;
|
package org.briarproject.briar.android.forum;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.identity.Author;
|
|
||||||
import org.briarproject.briar.api.identity.AuthorInfo;
|
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
|
||||||
import org.briarproject.briar.android.threaded.ThreadItem;
|
import org.briarproject.briar.android.threaded.ThreadItem;
|
||||||
import org.briarproject.briar.api.forum.ForumPostHeader;
|
import org.briarproject.briar.api.forum.ForumPostHeader;
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package org.briarproject.briar.android.hotspot;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.ResolveInfo;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@@ -17,8 +16,6 @@ import org.briarproject.briar.android.util.ActivityLaunchers.CreateDocumentAdvan
|
|||||||
import org.briarproject.nullsafety.MethodsNotNullByDefault;
|
import org.briarproject.nullsafety.MethodsNotNullByDefault;
|
||||||
import org.briarproject.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.nullsafety.ParametersNotNullByDefault;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import androidx.activity.result.ActivityResultLauncher;
|
import androidx.activity.result.ActivityResultLauncher;
|
||||||
@@ -29,14 +26,11 @@ import androidx.lifecycle.ViewModelProvider;
|
|||||||
import static android.content.Intent.ACTION_SEND;
|
import static android.content.Intent.ACTION_SEND;
|
||||||
import static android.content.Intent.EXTRA_STREAM;
|
import static android.content.Intent.EXTRA_STREAM;
|
||||||
import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;
|
import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;
|
||||||
import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;
|
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
|
||||||
import static android.view.View.INVISIBLE;
|
import static android.view.View.INVISIBLE;
|
||||||
import static android.view.View.VISIBLE;
|
import static android.view.View.VISIBLE;
|
||||||
import static androidx.transition.TransitionManager.beginDelayedTransition;
|
import static androidx.transition.TransitionManager.beginDelayedTransition;
|
||||||
import static org.briarproject.briar.android.AppModule.getAndroidComponent;
|
import static org.briarproject.briar.android.AppModule.getAndroidComponent;
|
||||||
import static org.briarproject.briar.android.hotspot.HotspotViewModel.getApkFileName;
|
import static org.briarproject.briar.android.hotspot.HotspotViewModel.getApkFileName;
|
||||||
import static org.briarproject.nullsafety.NullSafety.requireNonNull;
|
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
@@ -48,11 +42,9 @@ public class FallbackFragment extends BaseFragment {
|
|||||||
ViewModelProvider.Factory viewModelFactory;
|
ViewModelProvider.Factory viewModelFactory;
|
||||||
|
|
||||||
private HotspotViewModel viewModel;
|
private HotspotViewModel viewModel;
|
||||||
@Nullable
|
private final ActivityResultLauncher<String> launcher =
|
||||||
private final ActivityResultLauncher<String> launcher = SDK_INT >= 19 ?
|
|
||||||
registerForActivityResult(new CreateDocumentAdvanced(),
|
registerForActivityResult(new CreateDocumentAdvanced(),
|
||||||
this::onDocumentCreated) :
|
this::onDocumentCreated);
|
||||||
null;
|
|
||||||
private Button fallbackButton;
|
private Button fallbackButton;
|
||||||
private ProgressBar progressBar;
|
private ProgressBar progressBar;
|
||||||
|
|
||||||
@@ -89,12 +81,7 @@ public class FallbackFragment extends BaseFragment {
|
|||||||
beginDelayedTransition((ViewGroup) v);
|
beginDelayedTransition((ViewGroup) v);
|
||||||
fallbackButton.setVisibility(INVISIBLE);
|
fallbackButton.setVisibility(INVISIBLE);
|
||||||
progressBar.setVisibility(VISIBLE);
|
progressBar.setVisibility(VISIBLE);
|
||||||
|
launcher.launch(getApkFileName());
|
||||||
if (SDK_INT >= 19) {
|
|
||||||
requireNonNull(launcher).launch(getApkFileName());
|
|
||||||
} else {
|
|
||||||
viewModel.exportApk();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
viewModel.getSavedApkToUri().observeEvent(this, this::shareUri);
|
viewModel.getSavedApkToUri().observeEvent(this, this::shareUri);
|
||||||
}
|
}
|
||||||
@@ -110,23 +97,11 @@ public class FallbackFragment extends BaseFragment {
|
|||||||
progressBar.setVisibility(INVISIBLE);
|
progressBar.setVisibility(INVISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shareUri(Uri uri) {
|
private void shareUri(Uri uri) {
|
||||||
Intent i = new Intent(ACTION_SEND);
|
Intent i = new Intent(ACTION_SEND);
|
||||||
i.putExtra(EXTRA_STREAM, uri);
|
i.putExtra(EXTRA_STREAM, uri);
|
||||||
i.setType("*/*"); // gives us all sharing options
|
i.setType("*/*"); // gives us all sharing options
|
||||||
i.addFlags(FLAG_GRANT_READ_URI_PERMISSION);
|
i.addFlags(FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
Context ctx = requireContext();
|
|
||||||
if (SDK_INT <= 19) {
|
|
||||||
// Workaround for Android bug:
|
|
||||||
// ctx.grantUriPermission also needed for Android 4
|
|
||||||
List<ResolveInfo> resInfoList = ctx.getPackageManager()
|
|
||||||
.queryIntentActivities(i, MATCH_DEFAULT_ONLY);
|
|
||||||
for (ResolveInfo resolveInfo : resInfoList) {
|
|
||||||
String packageName = resolveInfo.activityInfo.packageName;
|
|
||||||
ctx.grantUriPermission(packageName, uri,
|
|
||||||
FLAG_GRANT_READ_URI_PERMISSION);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
startActivity(Intent.createChooser(i, null));
|
startActivity(Intent.createChooser(i, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import org.briarproject.nullsafety.NotNullByDefault;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
@@ -38,9 +37,6 @@ import androidx.annotation.UiThread;
|
|||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
|
||||||
import static android.os.Environment.DIRECTORY_DOWNLOADS;
|
|
||||||
import static android.os.Environment.getExternalStoragePublicDirectory;
|
|
||||||
import static java.util.Objects.requireNonNull;
|
import static java.util.Objects.requireNonNull;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static java.util.logging.Logger.getLogger;
|
import static java.util.logging.Logger.getLogger;
|
||||||
@@ -168,7 +164,6 @@ class HotspotViewModel extends DbViewModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
void exportApk(Uri uri) {
|
void exportApk(Uri uri) {
|
||||||
if (SDK_INT < 19) throw new IllegalStateException();
|
|
||||||
try {
|
try {
|
||||||
OutputStream out = getApplication().getContentResolver()
|
OutputStream out = getApplication().getContentResolver()
|
||||||
.openOutputStream(uri, "wt");
|
.openOutputStream(uri, "wt");
|
||||||
@@ -178,20 +173,6 @@ class HotspotViewModel extends DbViewModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void exportApk() {
|
|
||||||
if (SDK_INT >= 19) throw new IllegalStateException();
|
|
||||||
File path = getExternalStoragePublicDirectory(DIRECTORY_DOWNLOADS);
|
|
||||||
//noinspection ResultOfMethodCallIgnored
|
|
||||||
path.mkdirs();
|
|
||||||
File file = new File(path, getApkFileName());
|
|
||||||
try {
|
|
||||||
OutputStream out = new FileOutputStream(file);
|
|
||||||
writeApk(out, Uri.fromFile(file));
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
handleException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static String getApkFileName() {
|
static String getApkFileName() {
|
||||||
return "briar" + (DEBUG ? "-debug-" : "-") + VERSION_NAME + ".apk";
|
return "briar" + (DEBUG ? "-debug-" : "-") + VERSION_NAME + ".apk";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ import android.os.Bundle;
|
|||||||
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
|
||||||
|
|
||||||
public class ExitActivity extends Activity {
|
public class ExitActivity extends Activity {
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
@@ -15,8 +13,7 @@ public class ExitActivity extends Activity {
|
|||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle state) {
|
public void onCreate(Bundle state) {
|
||||||
super.onCreate(state);
|
super.onCreate(state);
|
||||||
if (SDK_INT >= 21) finishAndRemoveTask();
|
finishAndRemoveTask();
|
||||||
else finish();
|
|
||||||
LOG.info("Exiting");
|
LOG.info("Exiting");
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,15 +75,12 @@ import static org.briarproject.bramble.api.plugin.Plugin.State.ENABLING;
|
|||||||
import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING;
|
import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING;
|
||||||
import static org.briarproject.briar.android.BriarService.EXTRA_STARTUP_FAILED;
|
import static org.briarproject.briar.android.BriarService.EXTRA_STARTUP_FAILED;
|
||||||
import static org.briarproject.briar.android.BriarService.EXTRA_START_RESULT;
|
import static org.briarproject.briar.android.BriarService.EXTRA_START_RESULT;
|
||||||
import static org.briarproject.briar.android.TestingConstants.EXPIRY_DATE;
|
|
||||||
import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
|
import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
|
||||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PASSWORD;
|
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PASSWORD;
|
||||||
import static org.briarproject.briar.android.navdrawer.IntentRouter.handleExternalIntent;
|
import static org.briarproject.briar.android.navdrawer.IntentRouter.handleExternalIntent;
|
||||||
import static org.briarproject.briar.android.util.UiUtils.formatDateFull;
|
|
||||||
import static org.briarproject.briar.android.util.UiUtils.getDaysUntilExpiry;
|
import static org.briarproject.briar.android.util.UiUtils.getDaysUntilExpiry;
|
||||||
import static org.briarproject.briar.android.util.UiUtils.observeOnce;
|
import static org.briarproject.briar.android.util.UiUtils.observeOnce;
|
||||||
import static org.briarproject.briar.android.util.UiUtils.resolveColorAttribute;
|
import static org.briarproject.briar.android.util.UiUtils.resolveColorAttribute;
|
||||||
import static org.briarproject.briar.android.util.UiUtils.shouldWarnOldAndroidExpiry;
|
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
@@ -140,11 +137,9 @@ public class NavDrawerActivity extends BriarActivity implements
|
|||||||
setContentView(R.layout.activity_nav_drawer);
|
setContentView(R.layout.activity_nav_drawer);
|
||||||
|
|
||||||
BriarApplication app = (BriarApplication) getApplication();
|
BriarApplication app = (BriarApplication) getApplication();
|
||||||
if (!app.isInstrumentationTest()) {
|
if (IS_DEBUG_BUILD && !app.isInstrumentationTest()) {
|
||||||
if (IS_DEBUG_BUILD || shouldWarnOldAndroidExpiry()) {
|
navDrawerViewModel.showExpiryWarning()
|
||||||
navDrawerViewModel.showExpiryWarning()
|
.observe(this, this::showExpiryWarning);
|
||||||
.observe(this, this::showExpiryWarning);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
navDrawerViewModel.shouldAskForDozeWhitelisting().observe(this, ask -> {
|
navDrawerViewModel.shouldAskForDozeWhitelisting().observe(this, ask -> {
|
||||||
if (ask) showDozeDialog(R.string.dnkm_doze_intro);
|
if (ask) showDozeDialog(R.string.dnkm_doze_intro);
|
||||||
@@ -212,7 +207,7 @@ public class NavDrawerActivity extends BriarActivity implements
|
|||||||
public void onStart() {
|
public void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
lockManager.checkIfLockable();
|
lockManager.checkIfLockable();
|
||||||
if (IS_DEBUG_BUILD || shouldWarnOldAndroidExpiry()) {
|
if (IS_DEBUG_BUILD) {
|
||||||
navDrawerViewModel.checkExpiryWarning();
|
navDrawerViewModel.checkExpiryWarning();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -384,23 +379,14 @@ public class NavDrawerActivity extends BriarActivity implements
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String text;
|
|
||||||
if (IS_DEBUG_BUILD) {
|
|
||||||
text = getResources().getQuantityString(
|
|
||||||
R.plurals.expiry_warning, (int) daysUntilExpiry,
|
|
||||||
(int) daysUntilExpiry);
|
|
||||||
} else {
|
|
||||||
text = getResources().getQuantityString(
|
|
||||||
R.plurals.old_android_expiry_warning, (int) daysUntilExpiry,
|
|
||||||
formatDateFull(this, EXPIRY_DATE),
|
|
||||||
(int) daysUntilExpiry);
|
|
||||||
}
|
|
||||||
|
|
||||||
ViewGroup expiryWarning = findViewById(R.id.expiryWarning);
|
ViewGroup expiryWarning = findViewById(R.id.expiryWarning);
|
||||||
if (show) {
|
if (show) {
|
||||||
// show expiry warning text
|
// show expiry warning text
|
||||||
TextView expiryWarningText =
|
TextView expiryWarningText =
|
||||||
expiryWarning.findViewById(R.id.expiryWarningText);
|
expiryWarning.findViewById(R.id.expiryWarningText);
|
||||||
|
String text = getResources().getQuantityString(
|
||||||
|
R.plurals.expiry_warning, (int) daysUntilExpiry,
|
||||||
|
(int) daysUntilExpiry);
|
||||||
expiryWarningText.setText(text);
|
expiryWarningText.setText(text);
|
||||||
// make close button functional
|
// make close button functional
|
||||||
ImageView expiryWarningClose =
|
ImageView expiryWarningClose =
|
||||||
@@ -432,7 +418,7 @@ public class NavDrawerActivity extends BriarActivity implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View getView(int position, View convertView,
|
public View getView(int position, @Nullable View convertView,
|
||||||
ViewGroup parent) {
|
ViewGroup parent) {
|
||||||
View view;
|
View view;
|
||||||
if (convertView != null) {
|
if (convertView != null) {
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import info.guardianproject.panic.Panic;
|
|||||||
import info.guardianproject.panic.PanicResponder;
|
import info.guardianproject.panic.PanicResponder;
|
||||||
import info.guardianproject.trustedintents.TrustedIntents;
|
import info.guardianproject.trustedintents.TrustedIntents;
|
||||||
|
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
|
||||||
import static java.util.logging.Logger.getLogger;
|
import static java.util.logging.Logger.getLogger;
|
||||||
import static org.briarproject.briar.android.panic.PanicPreferencesFragment.KEY_LOCK;
|
import static org.briarproject.briar.android.panic.PanicPreferencesFragment.KEY_LOCK;
|
||||||
import static org.briarproject.briar.android.panic.PanicPreferencesFragment.KEY_PURGE;
|
import static org.briarproject.briar.android.panic.PanicPreferencesFragment.KEY_PURGE;
|
||||||
@@ -73,12 +72,7 @@ public class PanicResponderActivity extends BriarActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
finishAndRemoveTask();
|
||||||
if (SDK_INT >= 21) {
|
|
||||||
finishAndRemoveTask();
|
|
||||||
} else {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import javax.inject.Inject;
|
|||||||
|
|
||||||
import androidx.activity.result.ActivityResultLauncher;
|
import androidx.activity.result.ActivityResultLauncher;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentActivity;
|
import androidx.fragment.app.FragmentActivity;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
@@ -31,7 +30,6 @@ import static org.briarproject.briar.android.AppModule.getAndroidComponent;
|
|||||||
import static org.briarproject.briar.android.util.UiUtils.hideViewOnSmallScreen;
|
import static org.briarproject.briar.android.util.UiUtils.hideViewOnSmallScreen;
|
||||||
import static org.briarproject.briar.android.util.UiUtils.launchActivityToOpenFile;
|
import static org.briarproject.briar.android.util.UiUtils.launchActivityToOpenFile;
|
||||||
|
|
||||||
@RequiresApi(19)
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
public class ReceiveFragment extends Fragment {
|
public class ReceiveFragment extends Fragment {
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import javax.inject.Inject;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
@@ -29,7 +28,6 @@ import static java.util.Objects.requireNonNull;
|
|||||||
import static org.briarproject.briar.android.conversation.ConversationActivity.CONTACT_ID;
|
import static org.briarproject.briar.android.conversation.ConversationActivity.CONTACT_ID;
|
||||||
import static org.briarproject.briar.android.util.UiUtils.showFragment;
|
import static org.briarproject.briar.android.util.UiUtils.showFragment;
|
||||||
|
|
||||||
@RequiresApi(19)
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
public class RemovableDriveActivity extends BriarActivity {
|
public class RemovableDriveActivity extends BriarActivity {
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import javax.inject.Inject;
|
|||||||
|
|
||||||
import androidx.activity.result.ActivityResultLauncher;
|
import androidx.activity.result.ActivityResultLauncher;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentActivity;
|
import androidx.fragment.app.FragmentActivity;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
@@ -38,7 +37,6 @@ import static org.briarproject.bramble.util.LogUtils.logException;
|
|||||||
import static org.briarproject.briar.android.AppModule.getAndroidComponent;
|
import static org.briarproject.briar.android.AppModule.getAndroidComponent;
|
||||||
import static org.briarproject.briar.android.util.UiUtils.hideViewOnSmallScreen;
|
import static org.briarproject.briar.android.util.UiUtils.hideViewOnSmallScreen;
|
||||||
|
|
||||||
@RequiresApi(19)
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
public class SendFragment extends Fragment {
|
public class SendFragment extends Fragment {
|
||||||
|
|||||||
@@ -220,10 +220,10 @@ class BriarReportCollector {
|
|||||||
method.setAccessible(true);
|
method.setAccessible(true);
|
||||||
mobileEnabled = (Boolean) requireNonNull(method.invoke(cm));
|
mobileEnabled = (Boolean) requireNonNull(method.invoke(cm));
|
||||||
} catch (ClassNotFoundException
|
} catch (ClassNotFoundException
|
||||||
| NoSuchMethodException
|
| NoSuchMethodException
|
||||||
| IllegalArgumentException
|
| IllegalArgumentException
|
||||||
| InvocationTargetException
|
| InvocationTargetException
|
||||||
| IllegalAccessException e) {
|
| IllegalAccessException e) {
|
||||||
connectivityInfo
|
connectivityInfo
|
||||||
.add("MobileDataReflectionException", e.toString());
|
.add("MobileDataReflectionException", e.toString());
|
||||||
}
|
}
|
||||||
@@ -300,15 +300,12 @@ class BriarReportCollector {
|
|||||||
scanMode == SCAN_MODE_CONNECTABLE_DISCOVERABLE;
|
scanMode == SCAN_MODE_CONNECTABLE_DISCOVERABLE;
|
||||||
connectivityInfo.add("BluetoothDiscoverable", btDiscoverable);
|
connectivityInfo.add("BluetoothDiscoverable", btDiscoverable);
|
||||||
|
|
||||||
if (SDK_INT >= 21) {
|
// Is Bluetooth LE scanning and advertising supported?
|
||||||
// Is Bluetooth LE scanning and advertising supported?
|
boolean btLeScan = bt.getBluetoothLeScanner() != null;
|
||||||
boolean btLeScan = bt.getBluetoothLeScanner() != null;
|
connectivityInfo.add("BluetoothLeScanningSupported", btLeScan);
|
||||||
connectivityInfo.add("BluetoothLeScanningSupported", btLeScan);
|
boolean btLeAdvertise = bt.getBluetoothLeAdvertiser() != null;
|
||||||
boolean btLeAdvertise =
|
connectivityInfo.add("BluetoothLeAdvertisingSupported",
|
||||||
bt.getBluetoothLeAdvertiser() != null;
|
btLeAdvertise);
|
||||||
connectivityInfo.add("BluetoothLeAdvertisingSupported",
|
|
||||||
btLeAdvertise);
|
|
||||||
}
|
|
||||||
|
|
||||||
Pair<String, String> p = getBluetoothAddressAndMethod(ctx, bt);
|
Pair<String, String> p = getBluetoothAddressAndMethod(ctx, bt);
|
||||||
String address = p.getFirst();
|
String address = p.getFirst();
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
|||||||
import static android.os.Build.VERSION.SDK_INT;
|
import static android.os.Build.VERSION.SDK_INT;
|
||||||
import static androidx.core.view.ViewCompat.LAYOUT_DIRECTION_LTR;
|
import static androidx.core.view.ViewCompat.LAYOUT_DIRECTION_LTR;
|
||||||
import static java.util.Objects.requireNonNull;
|
import static java.util.Objects.requireNonNull;
|
||||||
import static java.util.logging.Level.INFO;
|
|
||||||
import static java.util.logging.Logger.getLogger;
|
import static java.util.logging.Logger.getLogger;
|
||||||
import static org.briarproject.briar.android.BriarApplication.ENTRY_ACTIVITY;
|
import static org.briarproject.briar.android.BriarApplication.ENTRY_ACTIVITY;
|
||||||
import static org.briarproject.briar.android.navdrawer.NavDrawerActivity.SIGN_OUT_URI;
|
import static org.briarproject.briar.android.navdrawer.NavDrawerActivity.SIGN_OUT_URI;
|
||||||
@@ -75,12 +74,6 @@ public class DisplayFragment extends PreferenceFragmentCompat {
|
|||||||
Locale locale = Localizer.getLocaleFromTag(tag);
|
Locale locale = Localizer.getLocaleFromTag(tag);
|
||||||
if (locale == null)
|
if (locale == null)
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
// Exclude RTL locales on API < 17, they won't be laid out correctly
|
|
||||||
if (SDK_INT < 17 && !isLeftToRight(locale)) {
|
|
||||||
if (LOG.isLoggable(INFO))
|
|
||||||
LOG.info("Skipping RTL locale " + tag);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
String nativeName = locale.getDisplayName(locale);
|
String nativeName = locale.getDisplayName(locale);
|
||||||
// Fallback to English if the name is unknown in both native and
|
// Fallback to English if the name is unknown in both native and
|
||||||
// current locale.
|
// current locale.
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import androidx.preference.ListPreference;
|
|||||||
import androidx.preference.PreferenceFragmentCompat;
|
import androidx.preference.PreferenceFragmentCompat;
|
||||||
import androidx.preference.SwitchPreferenceCompat;
|
import androidx.preference.SwitchPreferenceCompat;
|
||||||
|
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
|
||||||
import static java.util.Objects.requireNonNull;
|
import static java.util.Objects.requireNonNull;
|
||||||
import static org.briarproject.briar.android.AppModule.getAndroidComponent;
|
import static org.briarproject.briar.android.AppModule.getAndroidComponent;
|
||||||
import static org.briarproject.briar.android.settings.SettingsActivity.enableAndPersist;
|
import static org.briarproject.briar.android.settings.SettingsActivity.enableAndPersist;
|
||||||
@@ -71,17 +70,12 @@ public class SecurityFragment extends PreferenceFragmentCompat {
|
|||||||
@Override
|
@Override
|
||||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
if (SDK_INT < 21) {
|
// timeout depends on screenLock and gets disabled automatically
|
||||||
screenLock.setVisible(false);
|
LifecycleOwner lifecycleOwner = getViewLifecycleOwner();
|
||||||
screenLockTimeout.setVisible(false);
|
viewModel.getScreenLockTimeout().observe(lifecycleOwner, value -> {
|
||||||
} else {
|
screenLockTimeout.setValue(value);
|
||||||
// timeout depends on screenLock and gets disabled automatically
|
enableAndPersist(screenLockTimeout);
|
||||||
LifecycleOwner lifecycleOwner = getViewLifecycleOwner();
|
});
|
||||||
viewModel.getScreenLockTimeout().observe(lifecycleOwner, value -> {
|
|
||||||
screenLockTimeout.setValue(value);
|
|
||||||
enableAndPersist(screenLockTimeout);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -92,7 +86,6 @@ public class SecurityFragment extends PreferenceFragmentCompat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void checkScreenLock() {
|
private void checkScreenLock() {
|
||||||
if (SDK_INT < 21) return;
|
|
||||||
LifecycleOwner lifecycleOwner = getViewLifecycleOwner();
|
LifecycleOwner lifecycleOwner = getViewLifecycleOwner();
|
||||||
viewModel.getScreenLockEnabled().removeObservers(lifecycleOwner);
|
viewModel.getScreenLockEnabled().removeObservers(lifecycleOwner);
|
||||||
if (hasScreenLock(requireActivity())) {
|
if (hasScreenLock(requireActivity())) {
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import androidx.preference.Preference;
|
|||||||
import androidx.preference.PreferenceFragmentCompat;
|
import androidx.preference.PreferenceFragmentCompat;
|
||||||
import androidx.preference.PreferenceGroup;
|
import androidx.preference.PreferenceGroup;
|
||||||
|
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
|
||||||
import static java.util.Objects.requireNonNull;
|
import static java.util.Objects.requireNonNull;
|
||||||
import static org.briarproject.briar.android.AppModule.getAndroidComponent;
|
import static org.briarproject.briar.android.AppModule.getAndroidComponent;
|
||||||
import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
|
import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
|
||||||
@@ -49,11 +48,9 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
|||||||
private SettingsViewModel viewModel;
|
private SettingsViewModel viewModel;
|
||||||
private AvatarPreference prefAvatar;
|
private AvatarPreference prefAvatar;
|
||||||
|
|
||||||
@Nullable
|
private final ActivityResultLauncher<String[]> docLauncher =
|
||||||
private final ActivityResultLauncher<String[]> docLauncher = SDK_INT >= 19 ?
|
|
||||||
registerForActivityResult(new OpenImageDocumentAdvanced(),
|
registerForActivityResult(new OpenImageDocumentAdvanced(),
|
||||||
this::onImageSelected) :
|
this::onImageSelected);
|
||||||
null;
|
|
||||||
private final ActivityResultLauncher<String> contentLauncher =
|
private final ActivityResultLauncher<String> contentLauncher =
|
||||||
registerForActivityResult(new GetImageAdvanced(),
|
registerForActivityResult(new GetImageAdvanced(),
|
||||||
this::onImageSelected);
|
this::onImageSelected);
|
||||||
|
|||||||
@@ -1,57 +0,0 @@
|
|||||||
package org.briarproject.briar.android.splash;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
import org.briarproject.android.dontkillmelib.wakelock.AndroidWakeLockManager;
|
|
||||||
import org.briarproject.briar.R;
|
|
||||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
|
||||||
import org.briarproject.briar.android.activity.BaseActivity;
|
|
||||||
import org.briarproject.briar.android.controller.BriarController;
|
|
||||||
import org.briarproject.briar.android.logout.ExitActivity;
|
|
||||||
import org.briarproject.nullsafety.MethodsNotNullByDefault;
|
|
||||||
import org.briarproject.nullsafety.ParametersNotNullByDefault;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
|
|
||||||
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
|
|
||||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
|
||||||
import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
|
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
|
||||||
@ParametersNotNullByDefault
|
|
||||||
public class ExpiredOldAndroidActivity extends BaseActivity {
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
BriarController briarController;
|
|
||||||
@Inject
|
|
||||||
AndroidWakeLockManager wakeLockManager;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(@Nullable Bundle state) {
|
|
||||||
super.onCreate(state);
|
|
||||||
|
|
||||||
setContentView(R.layout.activity_expired_old_android);
|
|
||||||
findViewById(R.id.delete_account_button).setOnClickListener(v -> {
|
|
||||||
// Hold a wake lock to ensure we exit before the device goes to sleep
|
|
||||||
wakeLockManager.runWakefully(() -> {
|
|
||||||
// we're not signed in, just go ahead and delete
|
|
||||||
briarController.deleteAccount();
|
|
||||||
// remove from recent apps
|
|
||||||
Intent i = new Intent(this, ExitActivity.class);
|
|
||||||
i.addFlags(FLAG_ACTIVITY_NEW_TASK
|
|
||||||
| FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
|
|
||||||
| FLAG_ACTIVITY_NO_ANIMATION
|
|
||||||
| FLAG_ACTIVITY_CLEAR_TASK);
|
|
||||||
startActivity(i);
|
|
||||||
}, "DeleteAccount");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void injectActivity(ActivityComponent component) {
|
|
||||||
component.inject(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import javax.inject.Inject;
|
|||||||
|
|
||||||
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
||||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
|
||||||
import static androidx.preference.PreferenceManager.setDefaultValues;
|
import static androidx.preference.PreferenceManager.setDefaultValues;
|
||||||
import static java.lang.System.currentTimeMillis;
|
import static java.lang.System.currentTimeMillis;
|
||||||
import static java.util.logging.Logger.getLogger;
|
import static java.util.logging.Logger.getLogger;
|
||||||
@@ -50,12 +49,8 @@ public class SplashScreenActivity extends BaseActivity {
|
|||||||
public void onCreate(@Nullable Bundle state) {
|
public void onCreate(@Nullable Bundle state) {
|
||||||
super.onCreate(state);
|
super.onCreate(state);
|
||||||
|
|
||||||
if (SDK_INT >= 21) {
|
getWindow().setExitTransition(new Fade());
|
||||||
getWindow().setExitTransition(new Fade());
|
|
||||||
}
|
|
||||||
|
|
||||||
setPreferencesDefaults();
|
setPreferencesDefaults();
|
||||||
|
|
||||||
setContentView(R.layout.splash);
|
setContentView(R.layout.splash);
|
||||||
|
|
||||||
if (accountManager.hasDatabaseKey()) {
|
if (accountManager.hasDatabaseKey()) {
|
||||||
@@ -65,14 +60,9 @@ public class SplashScreenActivity extends BaseActivity {
|
|||||||
int duration =
|
int duration =
|
||||||
getResources().getInteger(R.integer.splashScreenDuration);
|
getResources().getInteger(R.integer.splashScreenDuration);
|
||||||
new Handler().postDelayed(() -> {
|
new Handler().postDelayed(() -> {
|
||||||
if (currentTimeMillis() >= EXPIRY_DATE) {
|
if (IS_DEBUG_BUILD && currentTimeMillis() >= EXPIRY_DATE) {
|
||||||
if (IS_DEBUG_BUILD) {
|
LOG.info("Expired");
|
||||||
LOG.info("Expired: debug build");
|
startNextActivity(ExpiredActivity.class);
|
||||||
startNextActivity(ExpiredActivity.class);
|
|
||||||
} else {
|
|
||||||
LOG.info("Expired: running on old Android");
|
|
||||||
startNextActivity(ExpiredOldAndroidActivity.class);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
startNextActivity(ENTRY_ACTIVITY);
|
startNextActivity(ENTRY_ACTIVITY);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import androidx.activity.result.contract.ActivityResultContracts.OpenDocument;
|
|||||||
import androidx.activity.result.contract.ActivityResultContracts.OpenMultipleDocuments;
|
import androidx.activity.result.contract.ActivityResultContracts.OpenMultipleDocuments;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
|
|
||||||
import static android.app.Activity.RESULT_CANCELED;
|
import static android.app.Activity.RESULT_CANCELED;
|
||||||
import static android.bluetooth.BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE;
|
import static android.bluetooth.BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE;
|
||||||
@@ -26,7 +25,6 @@ import static org.briarproject.bramble.util.AndroidUtils.getSupportedImageConten
|
|||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public class ActivityLaunchers {
|
public class ActivityLaunchers {
|
||||||
|
|
||||||
@RequiresApi(19)
|
|
||||||
public static class CreateDocumentAdvanced extends CreateDocument {
|
public static class CreateDocumentAdvanced extends CreateDocument {
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
@@ -48,7 +46,6 @@ public class ActivityLaunchers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(19)
|
|
||||||
public static class OpenDocumentAdvanced extends OpenDocument {
|
public static class OpenDocumentAdvanced extends OpenDocument {
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
@@ -69,13 +66,11 @@ public class ActivityLaunchers {
|
|||||||
putShowAdvancedExtra(i);
|
putShowAdvancedExtra(i);
|
||||||
i.setType("image/*");
|
i.setType("image/*");
|
||||||
i.addFlags(FLAG_GRANT_READ_URI_PERMISSION);
|
i.addFlags(FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
if (SDK_INT >= 19)
|
i.putExtra(EXTRA_MIME_TYPES, getSupportedImageContentTypes());
|
||||||
i.putExtra(EXTRA_MIME_TYPES, getSupportedImageContentTypes());
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(18)
|
|
||||||
public static class GetMultipleImagesAdvanced extends GetMultipleContents {
|
public static class GetMultipleImagesAdvanced extends GetMultipleContents {
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
@@ -84,13 +79,11 @@ public class ActivityLaunchers {
|
|||||||
putShowAdvancedExtra(i);
|
putShowAdvancedExtra(i);
|
||||||
i.setType("image/*");
|
i.setType("image/*");
|
||||||
i.addFlags(FLAG_GRANT_READ_URI_PERMISSION);
|
i.addFlags(FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
if (SDK_INT >= 19)
|
i.putExtra(EXTRA_MIME_TYPES, getSupportedImageContentTypes());
|
||||||
i.putExtra(EXTRA_MIME_TYPES, getSupportedImageContentTypes());
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(19)
|
|
||||||
public static class OpenImageDocumentAdvanced extends OpenDocument {
|
public static class OpenImageDocumentAdvanced extends OpenDocument {
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
@@ -99,13 +92,11 @@ public class ActivityLaunchers {
|
|||||||
putShowAdvancedExtra(i);
|
putShowAdvancedExtra(i);
|
||||||
i.setType("image/*");
|
i.setType("image/*");
|
||||||
i.addFlags(FLAG_GRANT_READ_URI_PERMISSION);
|
i.addFlags(FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
if (SDK_INT >= 19)
|
i.putExtra(EXTRA_MIME_TYPES, getSupportedImageContentTypes());
|
||||||
i.putExtra(EXTRA_MIME_TYPES, getSupportedImageContentTypes());
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(19)
|
|
||||||
public static class OpenMultipleImageDocumentsAdvanced
|
public static class OpenMultipleImageDocumentsAdvanced
|
||||||
extends OpenMultipleDocuments {
|
extends OpenMultipleDocuments {
|
||||||
@NonNull
|
@NonNull
|
||||||
@@ -115,8 +106,7 @@ public class ActivityLaunchers {
|
|||||||
putShowAdvancedExtra(i);
|
putShowAdvancedExtra(i);
|
||||||
i.setType("image/*");
|
i.setType("image/*");
|
||||||
i.addFlags(FLAG_GRANT_READ_URI_PERMISSION);
|
i.addFlags(FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
if (SDK_INT >= 19)
|
i.putExtra(EXTRA_MIME_TYPES, getSupportedImageContentTypes());
|
||||||
i.putExtra(EXTRA_MIME_TYPES, getSupportedImageContentTypes());
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import androidx.annotation.ColorRes;
|
|||||||
import androidx.core.app.NotificationCompat;
|
import androidx.core.app.NotificationCompat;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
|
||||||
import static androidx.core.app.NotificationCompat.VISIBILITY_PRIVATE;
|
import static androidx.core.app.NotificationCompat.VISIBILITY_PRIVATE;
|
||||||
|
|
||||||
public class BriarNotificationBuilder extends NotificationCompat.Builder {
|
public class BriarNotificationBuilder extends NotificationCompat.Builder {
|
||||||
@@ -24,7 +23,7 @@ public class BriarNotificationBuilder extends NotificationCompat.Builder {
|
|||||||
|
|
||||||
setLights(ContextCompat.getColor(context, R.color.briar_lime_400),
|
setLights(ContextCompat.getColor(context, R.color.briar_lime_400),
|
||||||
750, 500);
|
750, 500);
|
||||||
if (SDK_INT >= 21) setVisibility(VISIBILITY_PRIVATE);
|
setVisibility(VISIBILITY_PRIVATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BriarNotificationBuilder setColorRes(@ColorRes int res) {
|
public BriarNotificationBuilder setColorRes(@ColorRes int res) {
|
||||||
@@ -33,7 +32,7 @@ public class BriarNotificationBuilder extends NotificationCompat.Builder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public BriarNotificationBuilder setNotificationCategory(String category) {
|
public BriarNotificationBuilder setNotificationCategory(String category) {
|
||||||
if (SDK_INT >= 21) setCategory(category);
|
setCategory(category);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import android.view.View;
|
|||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
|
|
||||||
import com.google.android.material.snackbar.Snackbar;
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
import com.google.android.material.snackbar.Snackbar.Callback;
|
|
||||||
|
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.nullsafety.NotNullByDefault;
|
import org.briarproject.nullsafety.NotNullByDefault;
|
||||||
@@ -13,11 +12,7 @@ import androidx.annotation.ColorRes;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
|
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
|
||||||
import static android.view.View.INVISIBLE;
|
|
||||||
import static android.view.View.VISIBLE;
|
|
||||||
import static androidx.core.content.ContextCompat.getColor;
|
import static androidx.core.content.ContextCompat.getColor;
|
||||||
import static com.google.android.material.snackbar.Snackbar.LENGTH_INDEFINITE;
|
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public class BriarSnackbarBuilder {
|
public class BriarSnackbarBuilder {
|
||||||
@@ -37,24 +32,6 @@ public class BriarSnackbarBuilder {
|
|||||||
R.color.briar_button_text_positive));
|
R.color.briar_button_text_positive));
|
||||||
s.setAction(actionResId, onClickListener);
|
s.setAction(actionResId, onClickListener);
|
||||||
}
|
}
|
||||||
// Workaround for https://issuetracker.google.com/issues/64285517
|
|
||||||
if (duration == LENGTH_INDEFINITE && SDK_INT < 21) {
|
|
||||||
// Hide snackbar while it's opening to make bouncing less noticeable
|
|
||||||
s.getView().setVisibility(INVISIBLE);
|
|
||||||
s.addCallback(new Callback() {
|
|
||||||
@Override
|
|
||||||
public void onShown(Snackbar snackbar) {
|
|
||||||
snackbar.getView().setVisibility(VISIBLE);
|
|
||||||
// Request layout again in case snackbar is in wrong place
|
|
||||||
snackbar.getView().requestLayout();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDismissed(Snackbar snackbar, int event) {
|
|
||||||
snackbar.getView().setVisibility(INVISIBLE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ import androidx.annotation.ColorInt;
|
|||||||
import androidx.annotation.ColorRes;
|
import androidx.annotation.ColorRes;
|
||||||
import androidx.annotation.DrawableRes;
|
import androidx.annotation.DrawableRes;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
import androidx.annotation.UiThread;
|
import androidx.annotation.UiThread;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
@@ -108,8 +107,6 @@ import static java.util.logging.Level.WARNING;
|
|||||||
import static java.util.logging.Logger.getLogger;
|
import static java.util.logging.Logger.getLogger;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
import static org.briarproject.briar.android.TestingConstants.EXPIRY_DATE;
|
import static org.briarproject.briar.android.TestingConstants.EXPIRY_DATE;
|
||||||
import static org.briarproject.briar.android.TestingConstants.IS_OLD_ANDROID;
|
|
||||||
import static org.briarproject.briar.android.TestingConstants.OLD_ANDROID_WARN_DATE;
|
|
||||||
import static org.briarproject.briar.android.reporting.CrashReportActivity.EXTRA_APP_LOGCAT;
|
import static org.briarproject.briar.android.reporting.CrashReportActivity.EXTRA_APP_LOGCAT;
|
||||||
import static org.briarproject.briar.android.reporting.CrashReportActivity.EXTRA_APP_START_TIME;
|
import static org.briarproject.briar.android.reporting.CrashReportActivity.EXTRA_APP_START_TIME;
|
||||||
import static org.briarproject.briar.android.reporting.CrashReportActivity.EXTRA_INITIAL_COMMENT;
|
import static org.briarproject.briar.android.reporting.CrashReportActivity.EXTRA_INITIAL_COMMENT;
|
||||||
@@ -244,11 +241,6 @@ public class UiUtils {
|
|||||||
return (EXPIRY_DATE - now) / DAYS.toMillis(1);
|
return (EXPIRY_DATE - now) / DAYS.toMillis(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean shouldWarnOldAndroidExpiry() {
|
|
||||||
return IS_OLD_ANDROID &&
|
|
||||||
System.currentTimeMillis() >= OLD_ANDROID_WARN_DATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SpannableStringBuilder getTeaser(Context ctx, Spanned text) {
|
public static SpannableStringBuilder getTeaser(Context ctx, Spanned text) {
|
||||||
if (text.length() < TEASER_LENGTH)
|
if (text.length() < TEASER_LENGTH)
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
@@ -376,7 +368,6 @@ public class UiUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean hasKeyguardLock(Context ctx) {
|
public static boolean hasKeyguardLock(Context ctx) {
|
||||||
if (SDK_INT < 21) return false;
|
|
||||||
KeyguardManager keyguardManager =
|
KeyguardManager keyguardManager =
|
||||||
(KeyguardManager) ctx.getSystemService(KEYGUARD_SERVICE);
|
(KeyguardManager) ctx.getSystemService(KEYGUARD_SERVICE);
|
||||||
if (keyguardManager == null) return false;
|
if (keyguardManager == null) return false;
|
||||||
@@ -438,7 +429,6 @@ public class UiUtils {
|
|||||||
keyEvent.getKeyCode() == KEYCODE_ENTER;
|
keyEvent.getKeyCode() == KEYCODE_ENTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(api = 21)
|
|
||||||
public static void excludeSystemUi(Transition transition) {
|
public static void excludeSystemUi(Transition transition) {
|
||||||
transition.excludeTarget(android.R.id.statusBarBackground, true);
|
transition.excludeTarget(android.R.id.statusBarBackground, true);
|
||||||
transition.excludeTarget(android.R.id.navigationBarBackground, true);
|
transition.excludeTarget(android.R.id.navigationBarBackground, true);
|
||||||
@@ -480,7 +470,6 @@ public class UiUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isRtl(Context ctx) {
|
public static boolean isRtl(Context ctx) {
|
||||||
if (SDK_INT < 17) return false;
|
|
||||||
return ctx.getResources().getConfiguration().getLayoutDirection() ==
|
return ctx.getResources().getConfiguration().getLayoutDirection() ==
|
||||||
LAYOUT_DIRECTION_RTL;
|
LAYOUT_DIRECTION_RTL;
|
||||||
}
|
}
|
||||||
@@ -507,7 +496,7 @@ public class UiUtils {
|
|||||||
view.setVisibility(small ? GONE : VISIBLE);
|
view.setVisibility(small ? GONE : VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isSmallScreenRelativeToFontSize(Context ctx) {
|
private static boolean isSmallScreenRelativeToFontSize(Context ctx) {
|
||||||
Configuration config = ctx.getResources().getConfiguration();
|
Configuration config = ctx.getResources().getConfiguration();
|
||||||
if (config.fontScale == 0f) return true;
|
if (config.fontScale == 0f) return true;
|
||||||
return config.screenHeightDp / config.fontScale < 600;
|
return config.screenHeightDp / config.fontScale < 600;
|
||||||
@@ -546,7 +535,7 @@ public class UiUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void launchActivityToOpenFile(Context ctx,
|
public static void launchActivityToOpenFile(Context ctx,
|
||||||
@Nullable ActivityResultLauncher<String[]> docLauncher,
|
ActivityResultLauncher<String[]> docLauncher,
|
||||||
ActivityResultLauncher<String> contentLauncher,
|
ActivityResultLauncher<String> contentLauncher,
|
||||||
String contentType) {
|
String contentType) {
|
||||||
// Try GET_CONTENT, fall back to OPEN_DOCUMENT if available
|
// Try GET_CONTENT, fall back to OPEN_DOCUMENT if available
|
||||||
@@ -556,13 +545,11 @@ public class UiUtils {
|
|||||||
} catch (ActivityNotFoundException e) {
|
} catch (ActivityNotFoundException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
if (docLauncher != null) {
|
try {
|
||||||
try {
|
docLauncher.launch(new String[] {contentType});
|
||||||
docLauncher.launch(new String[] {contentType});
|
return;
|
||||||
return;
|
} catch (ActivityNotFoundException e) {
|
||||||
} catch (ActivityNotFoundException e) {
|
logException(LOG, WARNING, e);
|
||||||
logException(LOG, WARNING, e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Toast.makeText(ctx, R.string.error_start_activity, LENGTH_LONG).show();
|
Toast.makeText(ctx, R.string.error_start_activity, LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package org.briarproject.briar.android.widget;
|
package org.briarproject.briar.android.widget;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
@@ -27,7 +26,6 @@ public class TouchInterceptingLinearLayout extends LinearLayout {
|
|||||||
super(context, attrs, defStyleAttr);
|
super(context, attrs, defStyleAttr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(21)
|
|
||||||
public TouchInterceptingLinearLayout(Context context, AttributeSet attrs,
|
public TouchInterceptingLinearLayout(Context context, AttributeSet attrs,
|
||||||
int defStyleAttr, int defStyleRes) {
|
int defStyleAttr, int defStyleRes) {
|
||||||
super(context, attrs, defStyleAttr, defStyleRes);
|
super(context, attrs, defStyleAttr, defStyleRes);
|
||||||
|
|||||||
@@ -35,7 +35,6 @@
|
|||||||
<item
|
<item
|
||||||
android:id="@+id/action_transfer_data"
|
android:id="@+id/action_transfer_data"
|
||||||
android:title="@string/removable_drive_menu_title"
|
android:title="@string/removable_drive_menu_title"
|
||||||
android:visible="false"
|
|
||||||
app:showAsAction="never" />
|
app:showAsAction="never" />
|
||||||
</menu>
|
</menu>
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
@@ -55,10 +55,6 @@
|
|||||||
<item quantity="one">This is a test version of Briar. Your account will expire in %d day and cannot be renewed.</item>
|
<item quantity="one">This is a test version of Briar. Your account will expire in %d day and cannot be renewed.</item>
|
||||||
<item quantity="other">This is a test version of Briar. Your account will expire in %d days and cannot be renewed.</item>
|
<item quantity="other">This is a test version of Briar. Your account will expire in %d days and cannot be renewed.</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<plurals name="old_android_expiry_warning">
|
|
||||||
<item quantity="one">Android 4 is no longer supported. Briar will stop working on %s (in %d day). Please install Briar on a newer device and create a new account.</item>
|
|
||||||
<item quantity="other">Android 4 is no longer supported. Briar will stop working on %s (in %d days). Please install Briar on a newer device and create a new account.</item>
|
|
||||||
</plurals>
|
|
||||||
<string name="expiry_date_reached">This software has expired.\nThank you for testing!</string>
|
<string name="expiry_date_reached">This software has expired.\nThank you for testing!</string>
|
||||||
<string name="download_briar">To continue using Briar, please download the latest release.</string>
|
<string name="download_briar">To continue using Briar, please download the latest release.</string>
|
||||||
<string name="create_new_account">You will need to create a new account, but you can use the same nickname.</string>
|
<string name="create_new_account">You will need to create a new account, but you can use the same nickname.</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user