* If the info is taller than the icon, grow larger to fit it in
* Center icon vertically
* Move padding out of the header
* Revert some font sizes to how they were some time ago, a bit smaller
Yay!
As expected, a lot of the stuff in DB class is due to UpdateService
requiring it to process the downloaded indexes and insert data into
the database. Thus, this change is about removing that stuff from
the DB class and migrating to ContentProviders.
This required a bit of a change to the way that UpdateService decides
what to do with the data from indexes, but I hope it will make
understanding and changing UpdateService easier in the long term.
For example, it used to read the app details from database, then
if a repo wasn't updated (due to unchanged index) then it would take
the app details for that repo from the list of apps, and re-update
the database (or something like that).
Now, it has been refactored into the following methods:
* updateOrInsertApps(appsToUpdate);
* updateOrInsertApks(apksToUpdate);
* removeApksFromRepos(disabledRepos);
* removeApksNoLongerInRepo(appsToUpdate, updatedRepos);
* removeAppsWithoutApks();
* and probably some others...
Which hopefully are self-explanitory.
The recent change to implement single repo updates was re-implemented
with in light of the methods above. The interface to UpdateService for
scheduling a single repo update is the same as it was before, but
the implementation is completely different. Still works though.
Using batch content provider operations for repo updates,
but they suffer from the problem of not all being under the same
transaction, so if an insert/update stuffs up half way through, we
are left with only half of the update being complete. In the future,
if there is some way to implement notifications from the content provider's
applyBatch method, then we can do it all in the one transaction, and
still have notifications. Currently we break it into several calls
to applyBatch (and hence several transactions) to inform the user
of the progress.
Also adding the beginnings of some tests for AppProvider. In the future, I'll
work on adding better coverage, including instrumentation to test UI features.
==========================
Below is a list of many of the minor changes that also happened along the way
==========================
Make "Can update" tab stay up to date using content observer, rather
than manually deciding when to refresh the tab label as before.
The installed app list is now cached in Utils, because it is invoked
quite a few times, especially when rendering the app lists. The cache is
invalidated when PackageReceiver is notified of new apps.
The content providers don't notify changes if we are in batch mode.
I've left the notification at the end of the batch updates as the
responsibility of the UpdateService. However, it would be nice if this
was somehow handled by the content, as they are really the ones who
should worry about it.
Made curVersion, curVercode and curApk work with providers.
This was done by removing curApk (otherwise we'd need to query the db each
time we fetched one app to get a reference to that apk (resulting in hundreds
of queries). Instead, UpdateService now calculates curVercode and curVersion
and saves them to the database. We then use these where possible. If we really
need curApk (because we want info other than its version and code) we still have
the option of ApkProvider.Helper.find(app.id, app.curVercode). I considered
putting this inside the app value object, e.g. in getCurApk() but thought
better of it as it will likely result in people invoking it all the time,
without realising it causes a DB query.
incompatibleReasons required a minor UI tweak, removing the "min sdk"
ui element from the Apk list. It is replaced by the "Requires: %s" view
(which only appears when the app is incompatible). In the process, and in
response to some feedback from mvdan, I left the min sdk in there, but
only made it show when in "expert mode", just like the architecture.
In order to make the "installed apps" query work under test conditions,
needed to change the way the InstalledApkCache be replaceable with a
mock object.
Pause UIL loading on fast scroll of list, as the list was very choppy for
some reason.
Re-added "Last repo scan" info to the Manage Repo list view.
Fixed up some misc TODO's, removed some unused/empty functions.
Fixes issue #452. It turns out that recent versions of android do
this automatically, but my gingerbread emulator didn't.
In the process, I also refactored the getQuery method. It was previously
a void method that modified the state of the search view, which is a
bit counter-intuitive given it's name. Instead, I made it just a getter,
which calculates the query and returns it. That way, I was able to remove
mQuery from the fields in the search view. Generally, the less state we
need to worry about (e.g. fields in an object), the less assumptions we
need to make about whether that field has been set or not.
Solves issue # 453. Previously, it was reading one line at
a time of the index file. Turns out that the entire index is
only on about 5 lines, thus the 5th line is about 2mb. The
solution here is to switch to reading a fixed length of 4096
characters at a time rather than entire lines. This ends up
a bit more complex (because I wrote a custom tokenizer rather
than being able to use Java String methods such as indexOf).
There are still other memory issues on low memory devices,
to do with trying to parse ~1000 app value objects into memory,
each with numerous string objects associated with them. But
that particular issue will be solved in the future, with
the ContentProvider stuff.
A new repo can be added with only the fingerprint of the signing key, while
the regular tests are based on the entire public key (repo.pubkey). This
checks for the case when a repo only has the fingerprint and no pubkey yet.
In that case, it the pubkey presented by the index.jar file against the
stored fingerprint. If they match, then the whole pubkey in the index.jar
is stored.
The stored fingerprint is checked when a repo URI is received by FDroid to
prevent bad actors from overriding repo configs with other keys. So if the
fingerprint is not stored yet, calculate it and store it. If the fingerprint
is stored, then check it against the calculated fingerprint just to make sure
it is correct. If the fingerprint is empty, then store the calculated one.
This was in place before, but it needed to be updated for the new Repo
ContentProvider.
A repo URI can include info such as the current wifi SSID and BSSID that
the repo is hosted on. This is for when local repos are transmitted via
QRCode, NFC, etc. The receiver of this URI then checks to make sure it is
on the same wifi access point, and warns the user if not.
In the future, it should do more than just warn the user, but instead give
concrete actions for the user to take, like associating to that wifi.
Instead of ramming the fingerprint in the user field of the URI, use the
query string. Having the fingerprint in the user field was confusing some
browsers because it was trying to log in. The query string is the standard
place for such meta data, and has lots of room for expansion including
things like wifi network names. This will be useful later to determine if
both devices are currently on the same wifi network, and if they are local
repos, they should try syncing.
Its quite annoying to have the URI EditText in focus and the soft keyboard
pop up when viewing the RepoDetails since the vast majority of the time,
the user will be viewing the info there, not editing the URL.
This commit just moves the focus to the frame, and prevents the soft
keyboard from showing up by default. The user can still click on the URI
EditText to edit it and the soft keyboard will pop up.
URIs can come from clicking a web page, NFC transmission, QR Code scan, and
more. This code stops badly formed Uri strings from crashing F-Droid. It
then shows a Toast error message that it can't understand the incoming URI.
Android's scheme matcher is case-sensitive, so include
ALL CAPS versions to support ALL CAPS URLs in QR Codes.
QR Codes have a special ALL CAPS mode that uses a reduced
character set, making for more compact QR Codes.
This reverts:
We should not encourage all caps urls
2651b81792bdeed0db3c3960d0b7283536611012
The performance improvement from this will not be noticable (perhaps
there isn't one), however it is part of the bigger plan to move all of
the DB access to ContentProviders. This will make a big improvement to
the startup time of the app, given we are currently loading all of the
apps to populate the list of apps.
It will come at the cost of some apparantly weird code convensions. Most
notably, when loading data from a content provder, you only ask
for the fields that you intend to use. As a result of my Helper class which
converts results from the content providers cursor into Repo value objects,
there is no guarantee that certain attributes will be available on the
value object. E.g. if I load repos and only ask for "_ID" and "ADDRESS",
then it is meaningless to ask the resulting Repo object for its "VERSION"
(it wont be there), despite it being a perfectly legal attribute from
the Java compilers perspective.
Repo.id field has also been made private (sqlite is the only
entity should be able to set id's), and made id a long (sqlite stores
identifiers as longs rather than ints).
Now, clicking Update in "Repo Detail" only updates that repo, not all of
the repos. This will also be very useful for more transitory repos, like
p2p repos that are reached via bluetooth, local wifi, etc.
This keeps the same logic as was in place before, but splits out code from
onHandleIntent() so that it can be used to update specific repos, rather
than always updating all repos. This is needed for transient repos, like
p2p repos connected via bluetooth or local wifi.