Remove deprecated connectivity observer intent | broadcast receiver, use ConnectionLiveData

Signed-off-by: alperozturk <alper_ozturk@proton.me>
This commit is contained in:
alperozturk 2024-02-06 12:33:15 +01:00 committed by Alper Öztürk
parent f006d0d639
commit 0956ba300a
3 changed files with 120 additions and 61 deletions

View file

@ -9,36 +9,30 @@ import static it.niedermann.owncloud.notes.edit.EditNoteActivity.ACTION_SHORTCUT
import static it.niedermann.owncloud.notes.shared.util.NoteUtil.generateNoteExcerpt;
import static it.niedermann.owncloud.notes.widget.notelist.NoteListWidget.updateNoteListWidgets;
import static it.niedermann.owncloud.notes.widget.singlenote.SingleNoteWidget.updateSingleNoteWidgets;
import android.accounts.NetworkErrorException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.graphics.drawable.Icon;
import android.net.ConnectivityManager;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.AnyThread;
import androidx.annotation.ColorInt;
import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.preference.PreferenceManager;
import com.nextcloud.android.sso.AccountImporter;
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
import com.nextcloud.android.sso.exceptions.NoCurrentAccountSelectedException;
import com.nextcloud.android.sso.helper.SingleAccountHelper;
import com.nextcloud.android.sso.model.SingleSignOnAccount;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
@ -48,7 +42,6 @@ import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import it.niedermann.android.sharedpreferences.SharedPreferenceIntLiveData;
import it.niedermann.owncloud.notes.BuildConfig;
import it.niedermann.owncloud.notes.R;
@ -59,6 +52,7 @@ import it.niedermann.owncloud.notes.persistence.entity.CategoryWithNotesCount;
import it.niedermann.owncloud.notes.persistence.entity.Note;
import it.niedermann.owncloud.notes.persistence.entity.NotesListWidgetData;
import it.niedermann.owncloud.notes.persistence.entity.SingleNoteWidgetData;
import it.niedermann.owncloud.notes.shared.extensions.ContextExtensionsKt;
import it.niedermann.owncloud.notes.shared.model.ApiVersion;
import it.niedermann.owncloud.notes.shared.model.Capabilities;
import it.niedermann.owncloud.notes.shared.model.CategorySortingMethod;
@ -71,6 +65,7 @@ import it.niedermann.owncloud.notes.shared.model.NavigationCategory;
import it.niedermann.owncloud.notes.shared.model.NotesSettings;
import it.niedermann.owncloud.notes.shared.model.SyncResultStatus;
import it.niedermann.owncloud.notes.shared.util.ApiVersionUtil;
import it.niedermann.owncloud.notes.shared.util.ConnectionLiveData;
import it.niedermann.owncloud.notes.shared.util.NoteUtil;
import it.niedermann.owncloud.notes.shared.util.SSOUtil;
import retrofit2.Call;
@ -90,9 +85,7 @@ public class NotesRepository {
private final NotesDatabase db;
private final String defaultNonEmptyTitle;
/**
* Track network connection changes using a {@link BroadcastReceiver}
*/
private final LiveData<ConnectionLiveData.ConnectionType> connectionLiveData;
private boolean isSyncPossible = false;
private boolean networkConnected = false;
private String syncOnlyOnWifiKey;
@ -111,22 +104,6 @@ public class NotesRepository {
}
};
private final BroadcastReceiver networkReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateNetworkStatus();
if (isSyncPossible() && SSOUtil.isConfigured(context)) {
executor.submit(() -> {
try {
scheduleSync(getAccountByName(SingleAccountHelper.getCurrentSingleSignOnAccount(context).name), false);
} catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) {
Log.v(TAG, "Can not select current SingleSignOn account after network changed, do not sync.");
}
});
}
}
};
// current state of the synchronization
private final Map<Long, Boolean> syncActive = new ConcurrentHashMap<>();
private final Map<Long, Boolean> syncScheduled = new ConcurrentHashMap<>();
@ -152,9 +129,29 @@ public class NotesRepository {
this.apiProvider = apiProvider;
this.defaultNonEmptyTitle = NoteUtil.generateNonEmptyNoteTitle("", this.context);
this.syncOnlyOnWifiKey = context.getApplicationContext().getResources().getString(R.string.pref_key_wifi_only);
this.connectionLiveData = new ConnectionLiveData(context);
// Registers BroadcastReceiver to track network connection changes.
this.context.registerReceiver(networkReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
connectionLiveData.observeForever(connectionType -> {
if (connectionType == ConnectionLiveData.ConnectionType.Lost) {
networkConnected = false;
isSyncPossible = false;
Log.d(TAG, "No network connection.");
} else {
Log.d(TAG, "Network connection established with " + connectionType.name());
handleNetworkStatus();
}
if (isSyncPossible() && SSOUtil.isConfigured(context)) {
executor.submit(() -> {
try {
scheduleSync(getAccountByName(SingleAccountHelper.getCurrentSingleSignOnAccount(context).name), false);
} catch (NextcloudFilesAppAccountNotFoundException |
NoCurrentAccountSelectedException e) {
Log.v(TAG, "Can not select current SingleSignOn account after network changed, do not sync.");
}
});
}
});
final var prefs = PreferenceManager.getDefaultSharedPreferences(this.context);
prefs.registerOnSharedPreferenceChangeListener(onSharedPreferenceChangeListener);
@ -263,6 +260,7 @@ public class NotesRepository {
public void updateModified(long id, long modified) {
db.getAccountDao().updateModified(id, modified);
}
public void updateDirectEditingAvailable(final long id, final boolean available) {
db.getAccountDao().updateDirectEditingAvailable(id, available);
}
@ -727,7 +725,12 @@ public class NotesRepository {
@Override
protected void finalize() throws Throwable {
this.context.unregisterReceiver(networkReceiver);
LifecycleOwner lifecycleOwner = ContextExtensionsKt.lifecycleOwner(context);
if (lifecycleOwner != null) {
Log.d(TAG, "ConnectionLiveData Observer Removed");
connectionLiveData.removeObservers(lifecycleOwner);
}
super.finalize();
}
@ -888,41 +891,26 @@ public class NotesRepository {
}
public void updateNetworkStatus() {
try {
final var connMgr = (ConnectivityManager) this.context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connMgr == null) {
throw new NetworkErrorException("ConnectivityManager is null");
}
final var activeInfo = connMgr.getActiveNetworkInfo();
if (activeInfo == null) {
throw new NetworkErrorException("NetworkInfo is null");
}
if (activeInfo.isConnected()) {
networkConnected = true;
final var networkInfo = connMgr.getNetworkInfo((ConnectivityManager.TYPE_WIFI));
if (networkInfo == null) {
throw new NetworkErrorException("connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI) is null");
}
isSyncPossible = !syncOnlyOnWifi || networkInfo.isConnected();
if (isSyncPossible) {
Log.d(TAG, "Network connection established.");
} else {
Log.d(TAG, "Network connected, but not used because only synced on wifi.");
}
} else {
connectionLiveData.observeForever(connectionType -> {
if (connectionType == ConnectionLiveData.ConnectionType.Lost) {
networkConnected = false;
isSyncPossible = false;
Log.d(TAG, "No network connection.");
} else {
Log.d(TAG, "Network connection established with " + connectionType.name());
handleNetworkStatus();
}
} catch (NetworkErrorException e) {
Log.i(TAG, e.getMessage());
networkConnected = false;
isSyncPossible = false;
});
}
private void handleNetworkStatus() {
networkConnected = true;
isSyncPossible = !syncOnlyOnWifi;
if (isSyncPossible) {
Log.d(TAG, "Network connection established.");
} else {
Log.d(TAG, "Network connected, but not used because only synced on wifi.");
}
}

View file

@ -0,0 +1,13 @@
package it.niedermann.owncloud.notes.shared.extensions
import android.content.Context
import android.content.ContextWrapper
import androidx.lifecycle.LifecycleOwner
fun Context.lifecycleOwner(): LifecycleOwner? {
var curContext: Context? = this
while (curContext != null && curContext !is LifecycleOwner) {
curContext = (curContext as? ContextWrapper)?.baseContext
}
return curContext as? LifecycleOwner
}

View file

@ -0,0 +1,58 @@
package it.niedermann.owncloud.notes.shared.util
import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import androidx.lifecycle.LiveData
class ConnectionLiveData(val context: Context) : LiveData<ConnectionLiveData.ConnectionType>() {
private val connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
private val networkRequest = NetworkRequest.Builder().build()
enum class ConnectionType {
Lost, WiFi, Ethernet, MobileData, Other
}
init {
connectivityManager.registerNetworkCallback(
networkRequest,
object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
super.onAvailable(network)
val connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkCapabilities = connectivityManager.getNetworkCapabilities(network)
if (networkCapabilities != null) {
when {
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> {
postValue(ConnectionType.WiFi)
}
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> {
postValue(ConnectionType.Ethernet)
}
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> {
postValue(ConnectionType.MobileData)
}
else -> {
postValue(ConnectionType.Other)
}
}
}
}
override fun onLost(network: Network) {
super.onLost(network)
postValue(ConnectionType.Lost)
}
}
)
}
}