"Confirm swap" background was white but should have been blue.
SwapWorkflowActivity now extends ActionBarActivity instead of
FragmentActivity so older devices have an action bar (though it is
not styled with blue action buttons on android-10 devices).
Logging to help understand when the service is started, stopped,
restarted, and when individual components (e.g. web server, bonjour)
are started/stopped.
Fixed bug where service was moved to foreground during "restartIfEnabled"
because that is unneccesary if it is already in the foreground.
There is now a private [en|dis]ableSwappingSynchronous() method, to go
along with the public [en|dis]ableSwapping() method. The public method
knows about not spinning up tasks if already enabled, and also about
pushing the invocation to a background task. The private method just
blindly does what it is asked, without checking if it should be done,
and without running on a background task.
The same goes for the restartIfEnabled() method, it is responsible for
creating a single background task which runs in order: disable, and
then enable. This is actually the reason for having the synchronous
methods, rather than having, e.g., the public [en|dis]ableSwapping()
method know about threads. If that was the case, then restarting would
consist of starting, waiting for some form of notification that the
background task has completed, and then scheduling the enable task.
Now, it is a matter of calling both *SwappingSynchronous methods in
succession.
Removed LocalRepoService, replaced with SwapService.
Still TODO:
Manage threads. Currently everything is called from the
UI thread, which is a regression from the previous behaviour.
I'd like to manage this so that the code interacting with the
SwapManager doesn't need to bother itself with whether it is calling
from the UI thread or not.
The local repo service had many different methods and properties for
dealing with starting and stopping various things (webserver, bonjour,
in the future it will also need to know about bluetooth and Wifi AP).
The SwapService handles this stuff by delegating to specific classes
that are only responsible for one of these. Hopefully this will make
the process of enabling and disabling swap repos easier to reason
about.
The local repo service was also stopped and started quite regularly.
This meant it was up to the code making use of the service to know if
it was running or not, and to enable it if required.
The new SwapService is only started once (when the singleton
SwapManager is created for the first time). It should not use any more
resources, because it is a background service most the time, and it
is responsible for moving itself to the foreground when required (the
burden is not on the code consuming this service to know when to do
this).
By having the service running more often, it doesn't need to'
continually figure out if it needs to register or unregister listeners
for various properties (e.g. https enabled) or wifi broadcasts. The
listeners can stay active, and do nothing once notified if swapping is
not enabled.
Moved the timeout timer (which cancels the swap service after 15 mins)
into the SwapService, rather than being managed by the
SwapWorkflowActivity. Seems more appropriate for the service to know to
time itself out rather than the Activity, seeing as the Activity can
die and get GC'ed while the service is still running.
Finally, although there is nothing stopping code in F-Droid from
talking to the service directly, it is now handled by the SwapManager
singleton. This means that details such as using a Messenger or Handler
object in order to communicate via arg1 and arg2 is no longer required,
and instead methods with proper type signatures can be used. This is
similar (but not exactly the same) to how Android system services work.
That is, ask for a "Manager" object using getSystemService(), and then
use that to perform functionality and query state via that object,
which delegates to the service. Then we get the best of both worlds:
* Reasonable and type safe method signatures
* Services that are not tied to activity lifecycles, which persist
beyond the closing of the swap activity.
List views need to have their header view set _before_ an adapter is
assigned to them.
Was incorrectly passing an application context instead of an Activity
context to the progress dialog for swap.
Extend ActionBarActivity rather than FragmentActivity.
Don't persist swap workflow state to disk, only store it in the
singleton.
All the code from the activity and the fragments has been successfully
ported to the SwapWorkflowActivity + Views. Thus, the code is no longer
useful, as it was only kept over the previous WIP commits so that it
can be referred to to help re-implement fragments with views.
Currently the view to show after pressing the back button is defined
by individual InnerView classes. For example, the JoinWifiView always
says its previous step is the SelectAppsView. This works for the most
part, but doesn't work for:
* The first StartSwapView class (instead handled by a special case in
the Activity).
* WifiQrView which could either be going back to the NfcView or the
JoinWifiView, depending on a few cases, which the WifiQrView probably
shouldn't care about.
The state is saved to a preference file, but that is abstracted from
the SwapWorkflowActivity. It interacts with a SwapState object, which
is relatively safe in that you should not be able to save it into an
invalid state.
Note: At this point it is not tied to any service. I'm not sure it will
ever have to be either, as the service needs to persist state somewhere
anyway, so that will probably also end up saving to a preferences file
too.
As per the select apps list, there is quite a bit of business logic
in this class, which is now spread between the activity and the view.
The activity needs to handle some stuff, because the zxing library
routes intents to either an activity or a fragment.
There is quite a lot of business logic that was moved directly from
the fragment to the view. Before this feature is complete, that logic
should either be moved into the activity, or into some sort of
associated Presenter class for the JoinWifiView.
Not worrying about styling yet, just functionality. Added an InnerView
interface that these views can implement. Currently it asks them to
populate the menu. It may be slightly inefficient if we end up with a
popup menu, because it is called onPrepareOptionsMenu, but expects the
inner view to inflate the menu. However, for swap this shouldn't be an
issue, as all the menus pretty much fit in the action bar of most screen
sizes.
Added a SwapWorkflowActivity to re-implement the SwapActivity.
Once all the fragments have been refactored into views, then the
SwapActivity will be removed.
The NFC message now is handled by the FDroid activity, so it is treated
the same way as every other incoming repo URL. Because FDroid handles
incoming intents correctly, the NFC one just magically works when
the <intent-filter> is moved from ManageReposAcivity to FDroid without
further code changes.
The other change is that the two way swap only happens when both are
actually swapping. Otherwise, we will send a request for someone to
swap with us, when we are incapable of swapping with them.
Fixes#267.
Pretends that the swap repo never existed, by deleting it before adding
the new repo, and showing the same message that is shown when a new
repo is added. This does not change behaviour for existing non-swap
repos. They are not deleted before being added again, or else we would
lose the ability to verify the fingerprint of an existing repo is the
same as a newly added one with the same URL.
Note that this has the effect that the fingerprint/pubkey of the swap
repo is nuked when adding that repo manually.
Internationalised the string "BAD FINGERPRINT" while I was at it.
Force entire swap process to be portrait.
Although this is usually regarded as poor form, it is currently better
than the alternative which is the whole swap process poohing itself
when a device is rotated. In the future, it may be worthwhile investing
in designing a proper UX for landscape swap too. However the process
of swapping can be quite complex if not presented well, and so it might
end up being too much work to maintain two different UXes for landscape
and portrait.
See merge request !89
Although this is usually regarded as poor form, it is currently better
than the alternative which is the whole swap process poohing itself
when a device is rotated. In the future, it may be worthwhile investing
in designing a proper UX for landscape swap too. However the process
of swapping can be quite complex if not presented well, and so it might
end up being too much work to maintain two different UXes for landscape
and portrait.
The code for promoting an untrusted repo with no fingerprint, to
a repo with a pubkey and a fingerprint, was still there. The problem
was that it was being executed after we verified the index.jar cert
against the pubkey stored against the repo (which is empty for TOFU
repos).
This change makes it so that if we are updating a repo without a
fingerprint, then it is a TOFU request, and we don't try to verify
the certificates.
closes#85https://gitlab.com/fdroid/fdroidclient/merge_requests/85closes#254https://gitlab.com/fdroid/fdroidclient/issues/254
improved, but still rudimentary, hotspot handling in swap
My previous merge request fdroid/fdroidclient!78 was based on one broken assumption: `WIFI_STATE_UNKNOWN` means that the hotspot is active. Apparently, that's not always the case. Also, sometimes when the hotspot is active, its `WIFI_STATE_DISABLED`. Even worse, there is no broadcast message sent on final config of the hotspot. There is only a `WIFI_STATE_DISABLING` from turning off the wifi, but then never a broadcast for `WIFI_STATE_UNKNOWN` and/or `WIFI_STATE_DISABLED`. But I found some tricks that seem to work for now. We'll need to use your library, @mvdan, to really get good support of hotspots.
This also includes some basic UI tweaks to represent the hotspot mode in the swap wifi screen.
See merge request !79
Removes trailing slashes from URLs, replaces multiple consecutive forward
slashes in the path with a single slash. Canonicalizes the URL.
If the URL is invalid, display a message to the user and don't let it get
added.
NOTE: This does *not* normalize existing URLs in the database.
Previously it would only compare the details of a new repo to existing
ones if the new repo came via an intent. Now it does it whenever you
change the text in the new repo dialog (shouldn't be too much of a
performance hit, it isn't doing very much).
The things it (still) doesn't do is:
* verify that the url looks like a url
* sanitize the newly input uri and compare it to sanitized saved repos
The second point means that you can end up with:
http://10.0.1.50/ and
http://10.0.1.50
both in the list. I'm going to log an issue for this, because it should
be fixed, but doesn't need to hold this up.
This is really just a placeholder, there is lots of work to be done here.
Really, this screen should have the SSID of the hotspot, but we need to use
a private API to get that. Coming soon...
The icon is free software from:
https://commons.wikimedia.org/wiki/File:Wifi.svg
hotspot mode is not well represented with the WifiState stuff. It can be
active when the WifiState is DISABLED or UNKNOWN. Also, when switching
from active wifi to hotspot mode, WIFI_STATE_DISABLING broadcasts will be
sent, but WIFI_STATE_DISABLED/WIFI_STATE_UNKNOWN will not.
When a device is setup as a WiFi Access Point aka "hotspot", the standard
API for getting the WiFi settings returns nothing. We have to use a
separate API to get the IP address of the WiFi AP. As far as I could tell,
there is no public API for getting the SSID/BSSID of the WiFi AP, so for
now that is left blank. That means the wifi screen in swap is confusing
because it will say it is not attached when the device is a hotspot
@mvdan's https://github.com/mvdan/libaccesspoint should help there
#193https://gitlab.com/fdroid/fdroidclient/issues/193
To handle hotspots, this code will become more complicated. Therefore,
first simplify things by putting all of the logic into one place, rather
than spread out across FDroidApp, the receiver, and the service
On launch, we need to get the current state of the Wifi. We only need to
start the WifiStateChangeService on WIFI_STATE_ENABLED, since any other
wifi state will be received by WifiStateChangeReceiver, which will launch
WifiStateChangeService when appropriate.
This reduces the chance that WifiStateChangeService will start when it is
not needed.