kopia lustrzana https://github.com/ryukoposting/Signal-Android
Use newer APIs for detecting network changes.
rodzic
9b0dec7ece
commit
f091502949
|
@ -67,7 +67,7 @@ public class NewConversationActivity extends ContactSelectionActivity
|
|||
} else {
|
||||
Log.i(TAG, "[onContactSelected] Maybe creating a new recipient.");
|
||||
|
||||
if (SignalStore.account().isRegistered() && NetworkConstraint.isMet(this)) {
|
||||
if (SignalStore.account().isRegistered() && NetworkConstraint.isMet(getApplication())) {
|
||||
Log.i(TAG, "[onContactSelected] Doing contact refresh.");
|
||||
|
||||
AlertDialog progress = SimpleProgressDialog.show(this);
|
||||
|
|
|
@ -2,12 +2,8 @@ package org.thoughtcrime.securesms.jobmanager.impl;
|
|||
|
||||
import android.app.Application;
|
||||
import android.app.job.JobInfo;
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.Constraint;
|
||||
|
@ -43,14 +39,10 @@ public class NetworkConstraint implements Constraint {
|
|||
return "NETWORK";
|
||||
}
|
||||
|
||||
public static boolean isMet(@NonNull Context context) {
|
||||
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
|
||||
|
||||
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
|
||||
public static boolean isMet(@NonNull Application application) {
|
||||
return NetworkConstraintObserver.getInstance(application).hasInternet();
|
||||
}
|
||||
|
||||
|
||||
public static final class Factory implements Constraint.Factory<NetworkConstraint> {
|
||||
|
||||
private final Application application;
|
||||
|
|
|
@ -1,38 +1,156 @@
|
|||
package org.thoughtcrime.securesms.jobmanager.impl;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Application;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.NetworkRequest;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.jobmanager.ConstraintObserver;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
public class NetworkConstraintObserver implements ConstraintObserver {
|
||||
|
||||
private static final String REASON = Log.tag(NetworkConstraintObserver.class);
|
||||
|
||||
private final Application application;
|
||||
|
||||
public NetworkConstraintObserver(Application application) {
|
||||
private volatile Notifier notifier;
|
||||
private volatile boolean hasInternet;
|
||||
|
||||
private final Set<NetworkListener> networkListeners = new HashSet<>();
|
||||
|
||||
private static volatile NetworkConstraintObserver instance;
|
||||
|
||||
public static NetworkConstraintObserver getInstance(@NonNull Application application) {
|
||||
if (instance == null) {
|
||||
synchronized (NetworkConstraintObserver.class) {
|
||||
if (instance == null) {
|
||||
instance = new NetworkConstraintObserver(application);
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private NetworkConstraintObserver(Application application) {
|
||||
this.application = application;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(@NonNull Notifier notifier) {
|
||||
application.registerReceiver(new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
NetworkConstraint constraint = new NetworkConstraint.Factory(application).create();
|
||||
this.notifier = notifier;
|
||||
requestNetwork(0);
|
||||
}
|
||||
|
||||
if (constraint.isMet()) {
|
||||
notifier.onConstraintMet(REASON);
|
||||
@TargetApi(19)
|
||||
private static boolean isActiveNetworkConnected(@NonNull Context context) {
|
||||
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
|
||||
|
||||
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
|
||||
}
|
||||
|
||||
private void requestNetwork(int retryCount) {
|
||||
if (Build.VERSION.SDK_INT < 21 || retryCount > 5) {
|
||||
hasInternet = isActiveNetworkConnected(application);
|
||||
|
||||
application.registerReceiver(new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
hasInternet = isActiveNetworkConnected(context);
|
||||
|
||||
if (hasInternet) {
|
||||
notifier.onConstraintMet(REASON);
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
}, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
|
||||
}, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
|
||||
} else {
|
||||
NetworkRequest request = new NetworkRequest.Builder().addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
|
||||
.build();
|
||||
|
||||
ConnectivityManager connectivityManager = Objects.requireNonNull(ContextCompat.getSystemService(application, ConnectivityManager.class));
|
||||
connectivityManager.requestNetwork(request, Build.VERSION.SDK_INT >= 26 ? new NetworkStateListener26(retryCount) : new NetworkStateListener21());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasInternet() {
|
||||
return hasInternet;
|
||||
}
|
||||
|
||||
public void addListener(@Nullable NetworkListener networkListener) {
|
||||
synchronized (networkListeners) {
|
||||
networkListeners.add(networkListener);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeListener(@Nullable NetworkListener networkListener) {
|
||||
if (networkListener == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (networkListeners) {
|
||||
networkListeners.remove(networkListener);
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyListeners() {
|
||||
synchronized (networkListeners) {
|
||||
//noinspection SimplifyStreamApiCallChains
|
||||
networkListeners.stream().forEach(NetworkListener::onNetworkChanged);
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(21)
|
||||
private class NetworkStateListener21 extends ConnectivityManager.NetworkCallback {
|
||||
@Override
|
||||
public void onAvailable(@NonNull Network network) {
|
||||
Log.i(REASON, "Network available: " + network.hashCode());
|
||||
hasInternet = true;
|
||||
notifier.onConstraintMet(REASON);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLost(@NonNull Network network) {
|
||||
Log.i(REASON, "Network loss: " + network.hashCode());
|
||||
hasInternet = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(26)
|
||||
private class NetworkStateListener26 extends NetworkStateListener21 {
|
||||
private final int retryCount;
|
||||
|
||||
public NetworkStateListener26(int retryCount) {
|
||||
this.retryCount = retryCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnavailable() {
|
||||
Log.w(REASON, "No networks available");
|
||||
requestNetwork(retryCount + 1);
|
||||
}
|
||||
}
|
||||
|
||||
public interface NetworkListener {
|
||||
void onNetworkChanged();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -244,7 +244,7 @@ public final class JobManagerFactories {
|
|||
public static List<ConstraintObserver> getConstraintObservers(@NonNull Application application) {
|
||||
return Arrays.asList(CellServiceConstraintObserver.getInstance(application),
|
||||
new ChargingConstraintObserver(application),
|
||||
new NetworkConstraintObserver(application),
|
||||
NetworkConstraintObserver.getInstance(application),
|
||||
new SqlCipherMigrationConstraintObserver(),
|
||||
new DecryptionsDrainedConstraintObserver(),
|
||||
new NotInCallConstraintObserver());
|
||||
|
|
|
@ -2,11 +2,7 @@ package org.thoughtcrime.securesms.messages;
|
|||
|
||||
import android.app.Application;
|
||||
import android.app.Service;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.os.IBinder;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
@ -21,13 +17,13 @@ import org.thoughtcrime.securesms.R;
|
|||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.BackoffUtil;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraintObserver;
|
||||
import org.thoughtcrime.securesms.jobs.PushDecryptDrainedJob;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.messages.IncomingMessageProcessor.Processor;
|
||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
|
||||
import org.thoughtcrime.securesms.util.AppForegroundObserver;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.SignalWebSocket;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
|
||||
|
@ -42,22 +38,22 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
|
||||
/**
|
||||
* The application-level manager of our websocket connection.
|
||||
*
|
||||
* <p>
|
||||
* This class is responsible for opening/closing the websocket based on the app's state and observing new inbound messages received on the websocket.
|
||||
*/
|
||||
public class IncomingMessageObserver {
|
||||
|
||||
private static final String TAG = Log.tag(IncomingMessageObserver.class);
|
||||
|
||||
public static final int FOREGROUND_ID = 313399;
|
||||
private static final long REQUEST_TIMEOUT_MINUTES = 1;
|
||||
public static final int FOREGROUND_ID = 313399;
|
||||
private static final long REQUEST_TIMEOUT_MINUTES = 1;
|
||||
|
||||
private static final AtomicInteger INSTANCE_COUNT = new AtomicInteger(0);
|
||||
|
||||
private final Application context;
|
||||
private final SignalServiceNetworkAccess networkAccess;
|
||||
private final List<Runnable> decryptionDrainedListeners;
|
||||
private final BroadcastReceiver connectionReceiver;
|
||||
private final Application context;
|
||||
private final SignalServiceNetworkAccess networkAccess;
|
||||
private final List<Runnable> decryptionDrainedListeners;
|
||||
private final NetworkConstraintObserver.NetworkListener networkListener;
|
||||
|
||||
private boolean appVisible;
|
||||
|
||||
|
@ -92,22 +88,18 @@ public class IncomingMessageObserver {
|
|||
}
|
||||
});
|
||||
|
||||
connectionReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
synchronized (IncomingMessageObserver.this) {
|
||||
if (!NetworkConstraint.isMet(context)) {
|
||||
Log.w(TAG, "Lost network connection. Shutting down our websocket connections and resetting the drained state.");
|
||||
networkDrained = false;
|
||||
decryptionDrained = false;
|
||||
disconnect();
|
||||
}
|
||||
IncomingMessageObserver.this.notifyAll();
|
||||
}
|
||||
}
|
||||
};
|
||||
networkListener = this::networkChanged;
|
||||
NetworkConstraintObserver.getInstance(this.context).addListener(networkListener);
|
||||
}
|
||||
|
||||
context.registerReceiver(connectionReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
|
||||
private synchronized void networkChanged() {
|
||||
if (!NetworkConstraint.isMet(context)) {
|
||||
Log.w(TAG, "Lost network connection. Shutting down our websocket connections and resetting the drained state.");
|
||||
networkDrained = false;
|
||||
decryptionDrained = false;
|
||||
disconnect();
|
||||
}
|
||||
IncomingMessageObserver.this.notifyAll();
|
||||
}
|
||||
|
||||
public synchronized void notifyRegistrationChanged() {
|
||||
|
@ -160,9 +152,9 @@ public class IncomingMessageObserver {
|
|||
Log.d(TAG, String.format("Network: %s, Foreground: %s, FCM: %s, Censored: %s, Registered: %s, Proxy: %s",
|
||||
hasNetwork, appVisible, fcmEnabled, networkAccess.isCensored(), registered, hasProxy));
|
||||
|
||||
return registered &&
|
||||
return registered &&
|
||||
(appVisible || !fcmEnabled) &&
|
||||
hasNetwork &&
|
||||
hasNetwork &&
|
||||
!networkAccess.isCensored();
|
||||
}
|
||||
|
||||
|
@ -177,7 +169,7 @@ public class IncomingMessageObserver {
|
|||
public void terminateAsync() {
|
||||
INSTANCE_COUNT.decrementAndGet();
|
||||
|
||||
context.unregisterReceiver(connectionReceiver);
|
||||
NetworkConstraintObserver.getInstance(context).removeListener(networkListener);
|
||||
|
||||
SignalExecutors.BOUNDED.execute(() -> {
|
||||
Log.w(TAG, "Beginning termination.");
|
||||
|
|
Ładowanie…
Reference in New Issue