Rx needs to be used as the basis of the whole system, it doesn't make sense
to just have one small part handled by Rx.
RxJava is still used in InstallAppProviderService, so that would have to be
tackled separately.
Since it is possible to connect to a peer via NFC, "Swap back", QR Code,
etc. once a peer is successfully used, it can show up in the StartSwapView
list of peers.
This also switches to always using getActivity().getSwapService() to make
it easily traceable where that is happening. It shouldn't be happening in
SwapViews...
java.lang.IllegalStateException: Fatal Exception thrown on Scheduler.Worker thread.
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:62)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6128)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
at org.fdroid.fdroid.localrepo.peers.BonjourPeer.equals(BonjourPeer.java:34)
at java.util.HashMap.put(HashMap.java:427)
at java.util.HashSet.add(HashSet.java:217)
at rx.internal.operators.OperatorDistinct$1.onNext(OperatorDistinct.java:62)
at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.pollQueue(OperatorObserveOn.java:202)
at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber$2.call(OperatorObserveOn.java:162)
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
https://stackoverflow.com/a/602660
java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:851)
at java.util.HashMap$ValueIterator.next(HashMap.java:879)
at org.fdroid.fdroid.localrepo.LocalRepoManager.copyIconsToRepo(LocalRepoManager.java:296)
at org.fdroid.fdroid.localrepo.LocalRepoService$1.run(LocalRepoService.java:131)
SwapService is the thing that needs to be always running, and the last
thing killed. So it should start first, and stop last. So now, the user
clicking the button starts SwapService, which starts SwapWorkflowActivity.
This also eliminatings the "Loading" screen in favor of just showing the
StartSwapView with various inline progress indicators.
Instead of waiting for the user to make all the app selections, then click
next, this constantly regenerates the swap repo on each click of the app
list. This means that the swap repo is more likely to be immediately ready
when the user clicks next.
The Android back button provides a working back function, and the Swap
"close" button on the upper left already provides a reset function. So this
turns the "back" button to be a "try again" button which re-runs the
connection process.
The Receiver superclass is not reusing difficult code, but it is hiding the
simple list of UI configuration that it does.
This also eliminates the "error" TextView and just reuses the existing
TextView for error messages.
The most expensive part of this whole process is calculating the hash of the
whole APK. InstalledAppProvider already caches that, and the rest is OK to
query. If any particular part of the query is expensive, it could also be
moved to InstalledAppProviderService.
This moves all logic for setting up the local fdroid repo to its own
IntentService. That makes it much easier to interact with since things can
just use the static helper method to request it to update, and it'll do the
right thing.