diff --git a/src/org/kde/kdeconnect/Backends/BaseLinkProvider.java b/src/org/kde/kdeconnect/Backends/BaseLinkProvider.java index a95df464..78dae16e 100644 --- a/src/org/kde/kdeconnect/Backends/BaseLinkProvider.java +++ b/src/org/kde/kdeconnect/Backends/BaseLinkProvider.java @@ -23,10 +23,11 @@ package org.kde.kdeconnect.Backends; import org.kde.kdeconnect.NetworkPackage; import java.util.ArrayList; +import java.util.concurrent.CopyOnWriteArrayList; public abstract class BaseLinkProvider { - private final ArrayList connectionReceivers = new ArrayList<>(); + private final CopyOnWriteArrayList connectionReceivers = new CopyOnWriteArrayList<>(); public interface ConnectionReceiver { void onConnectionReceived(NetworkPackage identityPackage, BaseLink link); diff --git a/src/org/kde/kdeconnect/BackgroundService.java b/src/org/kde/kdeconnect/BackgroundService.java index 42be0f82..aeaf376e 100644 --- a/src/org/kde/kdeconnect/BackgroundService.java +++ b/src/org/kde/kdeconnect/BackgroundService.java @@ -61,12 +61,13 @@ public class BackgroundService extends Service { private final HashSet discoveryModeAcquisitions = new HashSet<>(); - public void acquireDiscoveryMode(Object key) { + public boolean acquireDiscoveryMode(Object key) { boolean wasEmpty = discoveryModeAcquisitions.isEmpty(); discoveryModeAcquisitions.add(key); if (wasEmpty) { onNetworkChange(); } + return wasEmpty; } public void releaseDiscoveryMode(Object key) { @@ -76,11 +77,18 @@ public class BackgroundService extends Service { } } - public static void addGuiInUseCounter(final Activity activity) { + public static void addGuiInUseCounter(Activity activity) { + addGuiInUseCounter(activity, false); + } + + public static void addGuiInUseCounter(final Activity activity, final boolean forceNetworkRefresh) { BackgroundService.RunCommand(activity, new BackgroundService.InstanceCallback() { @Override public void onServiceStart(BackgroundService service) { - service.acquireDiscoveryMode(activity); + boolean refreshed = service.acquireDiscoveryMode(activity); + if (!refreshed && forceNetworkRefresh) { + service.onNetworkChange(); + } } }); } diff --git a/src/org/kde/kdeconnect/Device.java b/src/org/kde/kdeconnect/Device.java index fdd1a362..5bb3d5f5 100644 --- a/src/org/kde/kdeconnect/Device.java +++ b/src/org/kde/kdeconnect/Device.java @@ -54,6 +54,7 @@ import java.util.HashSet; import java.util.Set; import java.util.Timer; import java.util.TimerTask; +import java.util.concurrent.CopyOnWriteArrayList; public class Device implements BaseLink.PackageReceiver { @@ -67,10 +68,11 @@ public class Device implements BaseLink.PackageReceiver { private DeviceType deviceType; private PairStatus pairStatus; - private final ArrayList pairingCallback = new ArrayList<>(); + + private final CopyOnWriteArrayList pairingCallback = new CopyOnWriteArrayList<>(); private Timer pairingTimer; - private final ArrayList links = new ArrayList<>(); + private final CopyOnWriteArrayList links = new CopyOnWriteArrayList<>(); private ArrayList incomingCapabilities; private ArrayList outgoingCapabilities; @@ -90,6 +92,12 @@ public class Device implements BaseLink.PackageReceiver { return unsupportedPlugins; } + private final CopyOnWriteArrayList pluginsChangedListeners = new CopyOnWriteArrayList<>(); + + public interface PluginsChangedListener { + void onPluginsChanged(Device device); + } + public enum PairStatus { NotPaired, Requested, @@ -640,8 +648,7 @@ public class Device implements BaseLink.PackageReceiver { boolean useEncryption = (!np.getType().equals(NetworkPackage.PACKAGE_TYPE_PAIR) && isPaired()); //Make a copy to avoid concurrent modification exception if the original list changes - ArrayList mLinks = new ArrayList<>(links); - for (final BaseLink link : mLinks) { + for (final BaseLink link : links) { if (link == null) continue; //Since we made a copy, maybe somebody destroyed the link in the meanwhile if (useEncryption) { link.sendPackageEncrypted(np, callback, publicKey); @@ -652,7 +659,7 @@ public class Device implements BaseLink.PackageReceiver { } if (!callback.success) { - Log.e("KDE/sendPackage", "No device link (of "+mLinks.size()+" available) could send the package. Package "+np.getType()+" to " + name + " lost!"); + Log.e("KDE/sendPackage", "No device link (of "+links.size()+" available) could send the package. Package "+np.getType()+" to " + name + " lost!"); backtrace.printStackTrace(); } @@ -859,12 +866,6 @@ public class Device implements BaseLink.PackageReceiver { return failedPlugins; } - public interface PluginsChangedListener { - void onPluginsChanged(Device device); - } - - private final ArrayList pluginsChangedListeners = new ArrayList<>(); - public void addPluginsChangedListener(PluginsChangedListener listener) { pluginsChangedListeners.add(listener); } diff --git a/src/org/kde/kdeconnect/UserInterface/MaterialActivity.java b/src/org/kde/kdeconnect/UserInterface/MaterialActivity.java index a04eb2ab..0d08d0c7 100644 --- a/src/org/kde/kdeconnect/UserInterface/MaterialActivity.java +++ b/src/org/kde/kdeconnect/UserInterface/MaterialActivity.java @@ -159,21 +159,33 @@ public class MaterialActivity extends AppCompatActivity { @Override protected void onStart() { super.onStart(); - BackgroundService.addGuiInUseCounter(this); + BackgroundService.addGuiInUseCounter(this, true); + BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() { + @Override + public void onServiceStart(BackgroundService service) { + service.addDeviceListChangedCallback("MaterialActivity", new BackgroundService.DeviceListChangedCallback() { + @Override + public void onDeviceListChanged() { + updateComputerList(); + } + }); + } + }); + updateComputerList(); } @Override protected void onStop() { BackgroundService.removeGuiInUseCounter(this); + BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() { + @Override + public void onServiceStart(BackgroundService service) { + service.removeDeviceListChangedCallback("MaterialActivity"); + } + }); super.onStop(); } - @Override - protected void onResume() { - super.onResume(); - updateComputerList(); - } - //TODO: Make it accept two parameters, a constant with the type of screen and the device id in //case the screen is for a device, or even three parameters and the third one be the plugin id? //This way we can keep adding more options with null plugin id (eg: about) diff --git a/src/org/kde/kdeconnect/UserInterface/PairingFragment.java b/src/org/kde/kdeconnect/UserInterface/PairingFragment.java index 75517d01..1eae0549 100644 --- a/src/org/kde/kdeconnect/UserInterface/PairingFragment.java +++ b/src/org/kde/kdeconnect/UserInterface/PairingFragment.java @@ -98,9 +98,10 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb public void run() { if (listRefreshCalledThisFrame) { - return; // This makes sure we don't try to call list.getFirstVisiblePosition() - // twice per frame, because the second time the list hasn't been drawn - // yet and it would always return 0. + // This makes sure we don't try to call list.getFirstVisiblePosition() + // twice per frame, because the second time the list hasn't been drawn + // yet and it would always return 0. + return; } listRefreshCalledThisFrame = true; @@ -183,9 +184,9 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb updateComputerList(); } }); - service.onNetworkChange(); } }); + updateComputerList(); } @Override @@ -199,12 +200,6 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb }); } - @Override - public void onResume() { - super.onResume(); - updateComputerList(); - } - @Override public void pairingClicked(Device device) { mActivity.onDeviceSelected(device.getDeviceId(), !device.isPaired() || !device.isReachable());