Locking down a GNOME setting

I think the dconf documentation and GNOME’s Sysadmin lockdown documentation (There’s this GNOME dconf wiki page too) could be clearer as well as being less duplicated and scattered. I’ve started trying to improve those documents directly.

In the meantime, here are some simple instructions for locking down some settings in GNOME 3 so the user cannot change them. Thanks to Ryan for explaining this to me. I’d welcome anyone’s extra corrections.

In this example, two children, Alice and Bobby, have user accounts on the computer called “alice” and “bobby”, and I want their accounts, and only their accounts, to not allow changing the list of application launchers in gnome-shell’s Dash, and not allow changing the desktop background. (Just as an example.)

Creating a dconf profile

I create a dconf profile for children in /etc/dconf/profile/, like so:

$ sudo nano /etc/dconf/profile/child

And I put this text in that file:


That tells dconf to use the “user database” named “user” as the writable store of settings for this dconf profile. Whatever database is on this first line will be used as the writable database. “user-db” (user database) just means that dconf should look in XDG_CONFIG_HOME/dconf for this database. That typically means ~/.config/dconf/, so this is specific to the user. This is what dconf uses by default if you haven’t assigned a dconf profile or changed the default “user” profile.

This example additionally tells dconf to use our “system database” named “child” for this dconf profile. Because this is not on the first line it is not writable. Because it’s a “system database” it will be in a shared location – typically /etc/dconf/db/. So this is a good place to specify some locks to prevent changes in the “user database” by anyone with this “child” profile. We could also use this “system database” to set some default values for the “child” profile.

The dconf overview documentation explains that profile file format more fully.

Creating a dconf lock file

Then I create a lock file for that “child” system database, like so, though the actual filename doesn’t matter:

$ sudo mkdir /etc/dconf/db/child.d
$ sudo nano /etc/dconf/profile/child.d/locks/00_some_locks

I put this text in that lock file:


I then call “dconf update” to tell it about the new profile and the lock file:

$ sudo dconf update

However, when you change the lock file, you’ll often need to do this too to make “dconf update” notice (see dconf  bug #741437):

$ sudo touch /etc/dconf/profile/child.d/locks
$ sudo dconf update

Using the dconf profile

Then I assign that dconf profile to the children’s user accounts, for instance by setting the DCONF_PROFILE environment variable in Alice’s .profile file:

$ sudo mkdir /home/alice/.profile

like so:

export DCONF_PROFILE="child"

If the child is already logged in then she’ll need to log out again to make her account use the new dconf profile. Also, don’t be foolish like me and put that in the .bash_rc file instead. That way lies confusion.

Note that the Alice can change her DCONF_PROFILE by changing that .profile file, to avoid the locks in her current profile. Or she can add a .bash_profile file to override .profile, or do something else clever. Locking of dconf settings is only for convenience – it isn’t meant to provide security. So if the user knows how to change her DCONF_PROFILE, she should probably be allowed to.

It would be nice if there was some GUI for managing profiles, and the databases’ locks, and default values. That seem doable.

I also wonder if there could be any API for applications to ask for admin access before making changes. Then a parent could, for instance, add just a single application launcher to the Dash. But I guess that would need us to either remove the dconf profile from the user (which needs a logout and login) or would need us to remove the lock from the dconf profiles’ system database, which would briefly unlock the setting for all other users who have the same dconf profile.

android-galaxyzoo: Superficial porting to Android 5.0 (Material design)

Here are some notes about my experience adapting android-galaxyzoo to Material design for Android 5.0 (Lollipop) though I only used the most superficial parts of Material design.

AppCompat v21

Android 5.0 (Lollipop) has a new UI theme and some new APIs. However, for the next few years, almost everyone will use the slightly awkward AppCompat v21 compatibility API instead to achieve most of the same behavior on older devices too. Chris Banes wrote up a nice overview of AppCompat v21, some of which I mention here again for completeness.

I’m using Gradle, as should you, so I added this to the dependencies block in my app/build.gradle file. You’ll want to use the latest version.

compile "com.android.support:appcompat-v7:21.0.3"


First, I switched from the dark Holo theme to the (AppCompat) dark Material theme by changing the parent theme in my styles.xml. See the Toolbar section below about the use of the “.NoActionBar” versions of these themes.

- <style name="AppTheme" parent="android:Theme.Holo">
+ <style name="AppTheme" parent="Theme.AppCompat.NoActionBar">

If you were using the light theme, that would be:

- <style name="AppTheme" parent="android:Theme.Holo.Light">
+ <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">

Note that we don’t use the android: prefix with the AppCompat theme, because the theme is being bundled directly into our app via the appcompatv21 library.

I then specified  the standard colorPrimary and colorAccent colors along with some more shenanigans to get the right text and icon colors in my toolbar.

I also used the TextAppearance_AppCompat_* widget styles instead of the regular textAppearance* style attributes, because it’s recommended in the Typography section of this official “Implementing Material Design in Your Android app” blog entry. However, I didn’t notice any difference in appearance, and I wonder why we wouldn’t just get the correct styles by just using the new overall theme.

I actually created a base style and two derived styles, to support Transitions – see below.


The new Toolbar widget replaces the ActionBar, though the documentation doesn’t actually say that yet. Generically, they are called the “App Bar” in the Material Design document. I’m not sure that I really got any benefit from using it because my App Bar doesn’t do anything special, but I wanted to use the latest API.

To use Toolbar instead of ActionBar,  you should derive from the .NoActionBar version of the theme, such as Theme.AppCompat.NoActionBar, though I used the regular Theme.AppCompat for a long time without noticing any difference.

Then you’ll want to add a Toolbar widget to the Layout XML files for every activity. I did that by creating a toolbar.xml file

<?xml version="1.0" encoding="utf-8"?>


and then I just including that from all the activity layouts like so:

<include layout="@layout/toolbar" />

I also specified the app:theme and app:popupTheme to get the right text and icon colors in my toolbar.

To use this toolbar as the App Bar, you need to derive from ActionBarActivity and call its setSupportActionBar() method. I did that in a utility function, like so:

Toolbar toolbar = (Toolbar) activity.findViewById(R.id.toolbar);


Android 5.0 adds the RecyclerView widget, available for older API levels via the support.recyclerview library. For instance, I added this to the dependencies block in my app/build.gradle file. You’ll want to use the latest version.

compile 'com.android.support:recyclerview-v7:21.0.0'

RecyclerView apparently replaces ListView and GridView, though the documentation doesn’t yet actually say that, adding confusion for new developers. I replaced my use of GridView with RecyclerView to get support for simple Material Design transitions.

Unfortunately, RecyclerView has no real cursor support, so it’s hard to use it to view data from a ContentProvider. This is particularly annoying because the API of ListView and GridView previously pushed us towards moving code into a ContentProvider. My own Cursor-based RecyclerView.Adapter is terribly inefficient and totally unsuitable for a large number of items.

There’s an awful lack of practical documentation or example code for RecyclerView, even for simple tasks like responding to a click. Until there’s an easier way, you’ll need some tedious boilerplate code to derive your RecyclerView.ViewHolder from View.OnClickListener and call setOnClickListener() on one of your child views.


I wanted the typical move-and-scale transition that we see in Material Design apps, so that clicking on one of many items makes its image expand and move into the subsequent detail activity, and shrink back again when you go back.

To achieve this, I had to specify various settings in my theme, but only Android 5.0 (Lollipop) devices support these transition items, so I created a base theme in res/styles.xml, and derived from it:

<?xml version="1.0" encoding="utf-8"?>

    <style name="AppTheme" parent="AppTheme.Base" />

    <style name="AppTheme.Base" parent="Theme.AppCompat.NoActionBar">
        <item name="colorPrimary">@color/color_primary</item>

I then created a styles.xml file just for API Level 21, by putting it in res/v21/styles.xml, where I derived from the base theme again:

<?xml version="1.0" encoding="utf-8"?>
    <style name="AppTheme" parent="AppTheme.Base">
        <item name="android:windowContentTransitions">true</item>
        <item name="android:windowAllowEnterTransitionOverlap">true</item>
        <item name="android:windowAllowReturnTransitionOverlap">true</item>

        <!-- specify shared element transitions -->
        <item name="android:windowSharedElementEnterTransition">
        <item name="android:windowSharedElementExitTransition">

I then defined that change_image_transform transition in my res/transition/change_image_transform.xml file, like so:

<?xml version="1.0" encoding="utf-8"?>

To actually use this transition on images, I needed to specify the android:transitionName on the two ImageViews in the the layout XML files for the two Activities (Fragments in my case).

Mostly this was all voodoo which I put together gradually after finding clues scattered around the internet. I haven’t found a good official example that shows this.

Unfortunately, the transition doesn’t seem to work when the user presses the Up button on the toolbar instead of using the standard Back button, even though that’s indistinguishable from Back for most users in most activities.

Metrics and Keylines

I made a fair effort to adapt my margins and padding to fit in with the Material Design Metrics and Keylines, which wasn’t too hard.

Unfortunately, the standard Android Button’s appearance is just as usless for Material design as it was for the Holo theme. It has a fake margin around its inside edges, which is part of its background graphic rather than any adjustable margin or paddng property.

So, to make the button’s sides actually flush with other widgets, and to position them properly on the layout grid, I had to specify a custom background image or color. But then I lost the nice Material Design ripple effect. I hope someone knows how to do this properly.

Activity classes without Toolbar support

There are a few helpful derived activity classes, such as AccountAuthenticatorActivity and PreferenceActivity, but these haven’t been changed to derived from ActionBarActivity, so you can’t call setSupportActionBar() on them. They can’t be changed without breaking compatibility, so you’ll have to reimplement them in your code. It’s not a lot of code but it’s an unpleasant developer experience.



android-galaxyzoo: Network I/O and UI responsiveness

While developing the Galaxy Zoo app for Android, I experienced problems with UI responsiveness while the app was downloading from, or uploading to, the remote server. I don’t mean just the usual problems caused by doing network I/O or file system access in the UI thread – mistakes that can often be caught by using Strict Mode. I mean that buttons didn’t respond to presses if the app happened to be doing I/O in an AsyncTask.doInBackground().

I solved this problem, but it was an incredibly frustrating journey. These notes might help the next person. So many Android apps are just a fancy way to interact with a website’s data, caching it locally, but the regular Android API doesn’t make that easy enough.

My app uses a ContentProvider, because the Android API seems to point us towards doing so, as I found while creating my experimental Android Glom app. The ContentProvider usually runs in the same process (and thread) as the main UI, so I don’t think this architecture was a cause of the UI responsiveness problem.

Thread+ResponseHandler versus AsyncTask

My ContentProvider needed to communicate with the remote server via REST messages, downloading images from the URLs that it then discovered and caching those images locally as well as storing data in its SQLite database. At first, I used the Thread class directly, with a UriRequestTask class derived from Runnable, that used HttpClient and accepted a (HttpClient) ResponseHandler. This was based on the example code in O’Reilly’s Programming Android (2nd Edition) book, in its “A Content Provider as a Facade for a RESTful Web Service” chapter (which you can see some of here).

Later, before I found the UI responsiveness problem, I replaced this Thread and RequestTask idea with AsyncTask because that seemed more robust and made it easier to get a result back to the main thread. I didn’t understand why the “Programming Android” book didn’t use AsyncTask in its ContentProvider. Yet later, I found that Strict Mode didn’t allow that use of AsyncTask in a SyncAdapter’s non-UI thread on some older devices (API version <15), causing an ExceptionInInitializerError with “Can’t create handler inside thread that has not called Looper.prepare()”. Maybe the authors found the same problem.

HttpURLConnection instead of HttpClient

Incidentally, I later realized that the Android developers now discourage use of HttpClient, because their version of HttpClient is buggy and they can’t update it without breaking compatibility. So I changed from HttpClient to HttpURLConnection (and here and here). Luckily, this fixed the endless redirect problem I (like others) was having with my uploads.

Again, I felt led astray by the “Programming Android” book, but books get out of date very quickly and the Android documentation apparently gives us new clues only reluctantly. Hopefully the 3rd edition will improve this.

Avoiding the user

This is when I noticed the UI responsiveness problem. I tried using Thread directly in various ways instead of AsyncTasks, fearing my own changes had caused it, but it made no difference.

I tried all kinds of tricks to avoid doing any I/O, even in the AsyncTasks, when the user was likely to be using the UI, trying to wait until it seemed that the user was idle and then doing some quick I/O before getting out of the way again. But the user is unpredictable and would still try to press a button now and then exactly when my app was doing some sneaky I/O.

After lots of imprecise testing, I was fairly sure that the problem was worse when the app happened to be doing some filesystem I/O, even just writing to the SQLite database, but it was definitely caused too by doing network I/O of even small JSON files. We should expect disk I/O to be worse than network I/O, of course.


I wanted to learn about Android’s SyncAdapter framework anyway, so I spent a week figuring that out despite its awful hand-wavy documentation. Luckily, it fixed the UI responsiveness problems. I think it helped partly because the I/O was now in a separate process, though that doesn’t feel like it should be necessary. Also, the SyncAdapter framework can decide when best to let the SyncAdapter do its work, based on the whole system. Presumably it can then prevent unrelated processes from making the UI responsiveness even worse.

Unfortunately, using SyncAdapter does mean that I lose control over when I may download items in advance. For instance, I often find that a new install of the app doesn’t fill up its initial list of ten items until five or ten minutes after the first start. In the meantime, the app requests the items directly when necessary. I call ContentProvider.requestSync(), with SYNC_EXTRAS_MANUAL, when I’m sure there’s work for the SyncAdapter to do, but it just seems to take this as a suggestion that it’s free to ignore.

Authenticator and Account

To use the SyncAdapter, I had to create an Authenticator, for which I needed an Account type, even if you are accessing your server anonymously. This account type will show up in the Settings->Accounts UI. Presumably this is why some other apps show up in the Accounts Settings, even though they don’t need any login. Maybe they are doing it just so they can use SyncAdapter.

SyncAdapter versus SharedPreferences/PreferenceFragment

So I started by storing the login details via the AccountManager instead of via SharedPreferences. I later discovered that the app’s SharedPreferences (such as how many items to download) were unavailable to the SyncAdapter’s separate process. That is documented as “currently this class does not support use across multiple processes“. So I later put other preferences in the account too. Unfortunately, the standard settings/preferences UI only uses SharedPreferences, so I have hacky code to keep the SharedPreferences and the Account in sync – see my onSharedPreferencesChange() override in my PreferenceFragment, so the account’s UserData is changed when the standard settings UI is used, via my hacky copyPrefToAccount method.

AccountManager versus main/UI thread

I also later found that you can’t use the AccountManager API from the main UI thread even though the documentation says things like “It is safe to call this method from the main thread”. The Firefox on Android developers discovered this too (1, 2, 3). So I moved that code to an AsyncTask (for example). If you don’t then you’ll get StrictMode exceptions at least on API level 15 and 16 – maybe others. StrictMode seems to have been on for Android Honeycomb, and some users seem to enable StrictMode, so you will see this as crash reports on some devices.


I also wanted to try out the Volley library. This isn’t an official part of the Android API. For instance, there’s not even an official way to add it as a dependency – I used the Volley package that mcxiaoke helpfully published to maven central. But Google use Volley in some of their own apps and they recommend Volley in the Android documentation. The video linked from there is well worth watching.

When I rewrote my HttpURL Connection-using code with Volley it seemed to make my downloads noticeably faster, probably because it avoids doing I/O in too many threads simultaneously. This was an easy win.

I couldn’t use Volley for my uploads, unfortunately, because Volley uses HttpClient on older Android versions whose HttpUrlConnection wasn’t good enough yet, causing the old endless-redirect problem again. So I use HttpURLConnection directly for that.


I also switched to using Picasso to fill ImageViews with bitmaps from our ContentProvider or directly from the internet, instead of my own AsyncTask. This simplified the code and gave me some extra caching, particularly simplifying my ListView/RecyclerView adaptor that previously had its own custom LruCache. For instance 1, 2, 3. Image loading just generally felt much faster everywhere that I used Picasso, though I don’t know exactly why.

Just filling an ImageView without blocking the UI seems like something unexciting that the Android API should already make easy.

Galaxy Zoo for Android

I just released my Galaxy Zoo android app to the Google Play store. The Zooniverse team have adopted it as their official Galazy Zoo app for Android.

Like the Galaxy Zoo website, it asks you questions about a picture of a galaxy, with each question depending on the previous question. This “Citizen Science” helps astronomers to analyze the huge amount of images of galaxies provided, for instance, by the Hubble Space Telescope. There are several other Zooniverse projects, though most require more thought and have more complicated user interaction.

screenshot_nexus4_api21_classify_first screenshot_nexus4_api21_list

I have already released several beta versions to a handful of helpful testers, but now I’m nervous about it being publicly available. I’d rather not be bombarded with one-star reviews if there’s a bug I haven’t caught yet or if people don’t like something about the questions themselves.

There was a previous Galaxy Zoo android app that I think was in use until around 2012, but it stopped working with the latest version of the server and apparently wasn’t updated. It’s no longer available from the Google Play store. This new Galaxy Zoo android app is open source on github, so it should have more future. For instance, that would let other developers investigate problems if there are server changes, even if I don’t (though I would). Patches and pull requests are very welcome. There are even a few minor issues that I’d already like help with.

I’ve been working on this for the past few weeks, using it as a real-world exercise to learn about Android development, trying to do everything properly. I’ve enjoyed diving into something new, and it feels good to have gained the experience. However, Android development ultimately feels just as awkward as every other development environment I’ve ever worked with – no more nor less. I’ll write some follow-up blog entries about the technical parts of the adventure.




Android: Changing action icon colors with Android 5.0’s drawable tinting

Android 5.0 (Lollipop), which is API version 21, supports tinting of drawables. So now you don’t need to recreate your monochrome action icons (in multiple sizes) just to show them in a different color in your app bar (ActionBar or ToolBar).

Unfortunately, drawable tinting isn’t available via the AppCompat library. That makes it useless for now unless you want to target only Android 5.0 devices, but here’s how to use it anyway. One day Android 5.0 might be old enough.

This is another part of my adventure in changing the color of stuff in Android’s app bar, after already figuring out how to change the color of the app bar’s text and standard icons.

Regular Drawables

Normally you’d just have the regular multiple .png files for your action item like so:


You would use these in your layout XML like so:


Or you would use them in code like this:


Tinted Drawables

You can now add a tinted version of the existing drawable like so:


With XML contents such as this:

<?xml version="1.0" encoding="utf-8"?>

That color_action_icons_tint could be hardcoded, but you’ll want to use the same one repeatedly via a color resource, like so:


With XML contents like this:

<?xml version="1.0" encoding="utf-8"?>
    <color name="color_action_icons_tint">#5a6518</color>

You can then refer to that tinted drawable just like any other drawable,

in your layout XML like so:


or in code like this:


Android: Changing the Toolbar’s text color and overflow icon color

Light on Dark and Dark on Light.

Android’s has normal (dark) and light themes, though it’s actually the light themes which are normally show in examples of the new Material design.

The light theme expects your App Bar1 (Toolbar or ActionBar) to have a light background color, so it gives you a dark title and dark overflow menu icon (the three vertical dots):


The dark theme expects your App Bar to have a dark background color, so it gives you a white title and white overflow menu icon:


This is true of both the Holo themes and the new Material themes.

If you want to use the light theme but want your App Bar to have a dark background, or use a dark theme and want your toolbar to have a light background, things get awkward. Arguably this might be unwise design anyway, but there’s nothing in the Material design guidelines advising against it.

It’s fairly easy to change the ActionBar‘s text color, but changing the color of its overflow icon is harder. It seems normal to provide a whole new overflow icon for your app, replacing the standard one, just to get the right color.

Android’s new Toolbar, which replaces ActionBar (with some awkward code), makes it easier to change the title text color and the color of the menu overflow icon (and the Up/Back icon). So now I finally have dark text and icons on my light background in the dark theme:


Toolbar theme and popupTheme

It took me ages to figure out how to do this, so hopefully the following explanation saves someone some time. I’d welcome any corrections.

My main theme derives from Theme.AppCompat (not Theme.AppCompat.Light), which is the dark Material theme for older devices, because I want most of the UI to be dark.

<style name="AppTheme" parent="AppTheme.Base" />
<!-- Base application theme.
     Defining this lets values-v21/styles.xml reuse it with changes. -->
<style name="AppTheme.Base" parent="Theme.AppCompat.NoActionBar">  
  <!-- colorPrimary is used, for instance, for the default ActionBar
       (but not Toolbar) background.
        We specify the same color for the toolbar background in 
        toolbar.xml.. -->
  <item name="colorPrimary">@color/color_primary</item>

  <!-- colorPrimaryDark is used for the status bar (with the
       battery, clock, etc). -->
  <item name="colorPrimaryDark">@color/color_primary_dark</item>

   <!-- colorAccent is used as the default value for
        colorControlActivated which is used to tint widgets. -->
  <item name="colorAccent">@color/color_accent</item>

(Update: I originally used Theme.AppCompat, manually setting windowActionBar to false, before learning of Theme.AppCompat.NoActionBar here, but I don’t notice any difference)

But that dark theme gives me light text and icons on the my light background of the App Bar:


I want to use a light color for the toolbar background even while using the dark theme.  So I’ll need to make the text and icons on my toolbar dark instead of the default white from the light theme. Incidentally, the Material Design Color Palette page seems to agree with me, using dark title text on the Lime color I’ve chosen, but using white on almost all other colors.

So my Toolbar’s XML layout specifies a different theme (app:theme when using AppCompat, or android:theme when targetting SDK >=21), like so:

  app:popupTheme="@style/Theme.AppCompat.NoActionBar" />

That toolbar theme specifies a textColorPrimary and textColorSecondary to change the color of the title text and of the menu overflow button. You could just specify the standard Theme.AppCompat.Light.NoActionBar theme for the toolbar, to get the dark text and overflow icon,  but I wanted to derive from my own theme and make only small changes, because I have no idea what else might be affected.

<style name="GalaxyZooThemeToolbarDarkOverflow" parent="Theme.AppCompat.NoActionBar">
  <!-- android:textColorPrimary is the  color of the title text
       in the Toolbar, in the Theme.AppCompat theme:  -->
  <item name="android:textColorPrimary">@color/abc_primary_text_material_light</item>

  <!-- android:textColorPrimaryInverse is the  color of the title
       text in the Toolbar, in the Theme.AppCompat.Light theme:  -->
  <!-- <item name="android:textColorPrimaryInverse">@color/abc_primary_text_material_light</item> -->

  <!-- android:actionMenuTextColor is the color of the text of
        action (menu) items in the Toolbar, at least in the
        Theme.AppCompat theme.
        For some reason, they already get the textColorPrimary
        when running on API 21, but not on older versions of
        Android, so this is only necessary to support older
        Android versions.-->
        <item name="actionMenuTextColor">@color/abc_primary_text_material_light</item>
  <!-- android:textColorSecondary is the color of the menu
       overflow icon (three vertical dots) -->
  <item name="android:textColorSecondary">@color/abc_secondary_text_material_light</item>

  <!-- This would set the toolbar's background color,
        but setting this also changes the popup menu's background,
        even if we define popupTheme for our <Toolbar> -->
  <!-- <item name="android:background">@color/color_primary</item> -->

This gives me the dark text and icons in my App Bar while using the dark theme:


That’s actually gray rather than black, and the white icons are really off-white, so you might want to use a custom color to have real black or white standard icons:

<item name="android:textColorSecondary">@color/my_black_icon_color</item>

Notice that the <Toolbar> also uses popupTheme (app:popuptheme when using AppCompat, or android:popupTheme when targetting SDK >=21). Without this, the overflow menu’s appearance is affected by the Toolbar’s style, leading to dark text on a dark background:


By specifying the Toolbar’s popupTheme, we can make its menu use our normal theme instead:


[1] “App Bar” seems to be the new official terminology. It’s used here and some other places I can’t find now.

Also see my entry about changing the colors of your own action icons with Android 5.0’s drawable tinting feature.

Looking at the Zooniverse code

Recently I’ve been looking over the Zooniverse citizen science project and its  source code on github, partly because it’s interesting as a user and partly because I thought writing an Android app for Galaxy Zoo would be a good learning exercise and something useful to open source.

So far my Android app can’t do more than show images, but I thought I’d write up some notes already. I hesitate to implement the Android App further because the classification decision tree is so tied up in the web site’s code, as I describe below.

Hopefully this won’t feel like an attack from a clueless outsider. I’m just a science enthusiast who happens to have spent years developing open source software in various communities. I’ve seen the same mistakes over and over again and I’ve seen how to make things better.

Zooniverse is organised by the Citizen Science Alliance (CSA). Incidentally, though the CSA has an organizational structure, I can’t see it’s actual legal form. Is it a foundation or a company? The zooniverse.org and citizensciencealliance.org domains are registered to Chris Lintott. Maybe it’s just a loose association of researchers with academic institutions assigning funds to work they care about, and maybe that’s normal in academia. The various Zooniverse employees actually seem to work for the member organisations such as the Adler Planetarium or the University of Oxford, though I guess some funding is for specific Zooniverse projects and some funding is for the overall Zooniverse development and hosting. That probably makes coordination difficult, like a big open source project.

Open Source

Since early 2013, the main Galaxy Zoo project has the code for it’s website on github along with the Zooniverse JavaScript library that it shares with other Zooniverse projects.

But most projects highlighted at zooniverse.org (such as Planet Four, Asteroid Zoo, Moon Zoo, or Solar StormWatch) don’t yet have their website’s code on github. This looks like a worrying trend. It doesn’t look like open sourcing has become the default as planned.

The zooniverse github repositories list is a poor overview, particularly because most of the respositories have no github description whatsover. Github should make them mandatory, even though they’d need to be updated later. Most projects don’t even have a basic description in their README.md either. Furthermore, I’d like to see a clear separation between front-ends, server-side code, and utilities (for processing data or for installing/maintaining servers.), maybe presented out on a github wiki page.

Also, they apparently have no plans to open source the server-side code (Ouroboros at api.zooniverse.org) that serves new subjects (such as galaxy images) to classify and receives classifications of these subjects. I think I’ve read that it’s a Ruby-On-Rails system. The client-side and server-side code is tightly bound, so this is a bit awkward. There is clearly room at least for some of the data structure and descriptions to be abstracted out and shared between the server, the client, and the analysis tools.

I can’t find any real documentation about the various Zooniverse code or APIs so there’s an awful chance of this blog post being the only introductory documentation that exists. I’d really welcome corrections and I’d gladly help. Neither can I find any place for public discussion of the software’s development, such as a mailing list. It’s hard for any open source project to mature without at least somewhere to discuss it.


Arfon Smith at Zooniverse wrote some blog entries about the Zooniverse Domain Model, Tools and Technologies, and Server-side logic (my title).  (Arfon has since left Zooniverse to work at Github). I also found some useful  documentation at the zooniverse npm.org page. But I had to look at the code and the network traffic to get a more complete picture.

Languages, Libraries, Frameworks

The zooniverse front-end web-sites generally seem to be written in CoffeeScript (a mostly nicer language on top of JavaScript), using the Spine framework, which seems to make it easier to separate data and code into an MVC structure and to write code that deals asynchronously with the server while caching some data locally.

Some Coffeescript is written inline with the HTML, in Eco (.eco) files.

The CSS is written in the Stylus syntax, as expected by hem, which they use to bundle the code up for deployment.

I’m no JavaScript expert, but these seem like fairly wise choices.

Zooniverse web sites communicate with the Ouroboros server using RESTful GET (get subjects to classify) and POST (return a classification of a subject) HTTP requests, using JSON syntax. I think the JSON syntax is generated/parsed by the base Spine.Module.  I don’t know of any implementation-independent documentation for this web API.

The website code uses the Zooniverse library  as a helper to communicate with the server, for instance to login, to get subjects, and to submit classifications, and to support the lists of recent and favourite subjetct. The Zooniverse library is also implemented in Coffescript. Strangely, the generated JavaScript is also checked into git. The Api class seems to be most interesting..

Questions and Answers

Let’s look at the Galaxy-Zoo website though its maybe the most complicated. It allows users to classify images of galaxies. Those images may be from one of several astronomical surveys, such as Sloan or UKIDSS. Each survey has an ID and a Workflow ID listed in config.coffee (with much duplication of magic numbers). Each survey has a human-readable description and title in the list of English strings.

Each survey has a question/decision tree under app/lib, such as Galaxy-Zoo’s sloan_tree.coffee.  I wonder if this generated or duplicated from somewhere in the server software.  Why are the long question titles duplicated and used as IDs for leadsTo instead of using short codes? Is this tree validated somehow during the build?

These IDs, Workflow IDs, and decision trees are listed in the Subject class.

Question IDs

The zero-based index of the questions in the decision trees are used as IDs when submitting the classification. For instance, a submitted classification POST might contain the following parameter to show that, when classifying a Sloan image, for the “Is there any sign of a spiral arm pattern” question (sloan-3, and the 4th question asked of me) I answered “Spiral” (a-0):

classification[annotations][4][sloan-3]: "a-0"

These implicit IDs, such as sloan-3, are also used in the translations,  and throughout the code. For instance, to reuse some translation strings, to decide if there should be a talk-page link. That i18n hack in particular belongs as an association in the decision tree.

These implicit IDs are also used in the CSS (via the Stylus .styl files) to identify the relevant icons. The icons are in one workflow.png file in order to use the CSS Sprites technique for performance). The various sub-parts of that image are selected by CSS in common.styl.

This seems very fragile. It would be safer if the icon files were stored separately and then the combined file was generated, along with that .styl CSS. I guess that the icons are already stored separately somewhere, maybe as SVG. One parent file could define the decision tree and all the associated descriptions and icon files.

Ideally much of this structure would be described in configuration files separately from the code. That generalisation would allow more code reuse between Zooniverse projects and could allow reuse by other front-ends such as iPhone and Android apps. Presumably it’s this fragility that has caused Galaxy Zoo to withdraw its previous mobile apps. Even with such an improvement, you’d still need a proper release process to coordinate development of interdependent software.

Subject and Classification

Galaxy-Zoo has a Subject class, as does the Operation War Diaries project. These usually derive from the base Subject class in the zooniverse library  ,though the Snapshot Serengeti Subject class does not.

The Ouroboros server at at api.zooniverse.org provides a list of subjects for each group (a group is a survey, I think) to be classified via JSON. Here is the list of subjects for Galaxy Zoo’s Sloan survey. And here is the subjects list for Snapshot Serengeti with a simpler URI because there is only one group/survey.

The surveyId (for the group) for Galaxy Zoo is chosen randomly, though it’s currently hard-coded to always choose the Sloan survey. This JSON message contains the URLs of images for each  subject, in the list of “locations”. The Subject’s fetch() method calls the Api.get() method from the Zooniverse library and then creates Subjects for each item that the JSON message mentions.

The Subject’s constructor seems to take theJSON fragment to populate its member fields using the default Spine.Model’s AJAX functionality.

Galaxy-Zoo has a Classification class, and Snapshot Serengeti has one too. There doesn’t seem to be any common base Classification class in the zooniverse library. The Classification’s send() method calls the Classification’s toJSON() method before POSTING the message to the server via the Zooniverse library’s Api.post() method.

It’s hard to see any great commonality between the various projects.
For instance, a Galaxy Zoo classification is a series of answers to multiple-choice questions, with the questions being from a decision tree. I guess that Snapshot Serengeti’s animal classification is similar, though you can provide multiple sets of answers to the same questions about what animal it is and what it is doing, to identify multiple animals in each image. Moon Zoo and Planet Four ask you to draw specific shapes on an image and also classify each shape you’ve drawn, probably resulting in coordinates and identifications.

I wonder if the server-side code has any common model for these data structures or if the classifications just get fed into project-specific databases for project-specific data analysis later.

Android Glom Experiments

Over the past few weeks I’ve been diving into Android development using a semi-realistic project to force me to learn properly. I wrote a rough first version of a read-only Glom database UI for Android, called android-glom. So now there’s a version in gtkmm (C++), Qt (C++), GWT (Java) and Android (Java). It’s a good way to really try out a framework and I’ve really enjoyed doing that with no pressure.

Here are some of my thoughts about the experience. I’d welcome feedback about the opinions I’ve formed and about the code I’ve written.

I’ve been doing this while reading O’Reilly’s Programming Android book which is pretty good. I had already read the Busy Coder’s Guide to Android Development a few years ago, which I also liked, but I didn’t realise until recently that it’s been kept up to date as a subscription, because Amazon only has the old edition.

Android Studio

I tried out Android Studio for this project. It’s not quite officially stable but I already find it preferable to Eclipse even though its UI is only slightly less cluttered than Eclipse. It has never asked me to choose a “Perspective”, which is nice. Like Eclipse, it has refactoring tools so you can move Java code around and rename stuff easily. I miss this now when I use C++.


Android doesn’t really support JDBC, making sure that you don’t even try to access an external database server on a tablet or handheld that probably doesn’t have a reliable connection. Those database servers are not meant to be exposed directly on the internet anyway. But it’s still annoying that have to use a similar-but-separate Android-specific and SQLite-specific database API (SQLiteDatabase, SQLiteOpenHelper and Cursor) instead, making code less portable.

Luckily I was still able to reuse much of my SQL-building and data-structure Java code from gwt-glom with just minor changes.

Activities and Fragments

Fragments are a fairly new way to let you rearrange your Android UI in various ways for different sized screens or different orientations. For instance a tablet UI might have one Activity that shows a list fragment at the left and a detail fragment at the right, depending on what item is selected in the list. But a handset version of that UI might open a second detail Activity to show that detail fragment, because it doesn’t have a big enough screen to show both at once.

Unfortunately, there are various official examples that use fragments to support both tablet and handet UIs in one app, but they don’t all use the same techniques or API. For instance, the “Building a Flexible UI” documentation instead suggests just replacing the one fragment in the one single activity for the handset UI and using FragmentTransaction.addToBackStack() so the back button works.

However, the Master/Detail new-activity template code used in Eclipse and Android Studio uses the multiple Activity idea (only one Activity is ever used in the Tablet UI), setting an mTwoPane boolean after detecting which XML layout file has been loaded. This works because you can specify separate layouts (or other resources) for Android to use depending on, for instance, screen size or orientation, and you just need to check what it has decided to use.

So this is the system that I’ve used, later checking that mTwoPane boolean when I want to navigate to another part of the UI, either telling the main Activity to do something with one of its fragments, putting the necessary parameters in a Bundle given to Fragment.setArguments() or just using startActivity() to start a new Activity with the appropriate parameters in its Intent. It’s slightly annoying that fragments take a Bundle but Activities take an Intent, with both having very similar but separate APIs.

Content Providers

Many parts of the Android API, such as ListView, ListFragment, and ListActivity, assume the use of a Cursor to access data, which in turn requires that you use a either a SQLiteDatabase or a ContentProvider.

The Android API documentation implicitly pushes you, via deprecation,  to use a  Content Provider, rather than just a SqliteDatabase, to separate your UI and data into separate processes even when you have no need to share your application’s data with other applications, even though the high-level documentation says “You don’t need to develop your own provider if you don’t intend to share your data with other applications.”

Specifically, you can tell your ListView, ListFragment, or ListActivity to show your SQLite database data via a CursorAdapter, such as SimpleCursorAdapter, which takes a Cursor. That Cursor can be the result of a SQLiteDatabase.query() or rawQuery(). But you’ll need to call Activity.startManagingCursor() on that Cursor and that is deprecated (probably because its not asynchronous) in favour of using CursorLoader (by implementing LoaderManager). And that means using a ContentProvider. See the “Running a Query with a CursorLoader” documentation. I wish that the documentation and examples just started off with this clear recommendation.

You can instead implement a custom CursorLoader that uses a SQLiteDatabase directly, but you then lose some functionality such as automatic ListView updating via notification when the data changes. And I think I’ve read of other ListView functionality that only works with a ContentProvider but I can’t find that documentation now. I think it was something about searching or auto-completion.

Content Providers are a bit awkard

Unfortunately a ContentProvider doesn’t provide quite as much loose binding as you’d hope. The ContentProvider API is very much like a SQL API. Most example code seems to just expose the SQLite database structure directly, sometimes with a simple mapping of column names as a thin separation. Given that this is the most common ContentProvider implementation that gets cargo-culted, it seems that it should be a lot less verbose.

(Update: I noticed that the mapping of external column names to internal columns names is useless anyway because you end up exposing the internal column names when your Content Provider’s query() returns the database query’s cursor as your Content Provider query()’s cursor. Client code will often then need those internal database column names to call Cursor.getColumnIndex() to then get the values in the columns. This is only a problem when you don’t specify specific columns, which would then be mapped by SQLiteQueryBuilder.setProjectionMap().)

I also don’t like how this forces so much implementation code to be forced into one ContentProvider API, separated only by switch statements in the query(), insert(), update() and delete() implementations. I’d like an easy way to delegate my various ContentProvider URL implementations to separate classes.

Here’s a link to my ContentProvider to show what I mean. It feels like a mess.

A database as a web service

On the other hand, it’s good that the ContentProvider provides a route to storing your data on the internet instead, maybe just caching it locally, without changing your UI code. For instance, using some RESTful service, whose API would closely match a database API.

In fact, I’d like some easy way to just expose a database on the web, with multiple user-level and table-level access control. I know that developers spend huge amounts of time implementing very specific “business logic” web APIs to hide their underlying databases, and I know that developers rightly fear anyone having direct access to their databases. But couldn’t it be done properly? I guess that most of these systems have much the same code with much the same security mistakes, just to put the names of their database tables and columns behind a few levels of programming language class names, method names and parameter names that provide just a thin sense of security and a token hint at modularity.

I’ve found a few systems that do this, but I have no idea of which ones are trusted and used much.


Family Research

I’ve been doing some family tree research. My parents and their parents were so adverse to talking that I unfairly associate Scottishness with unusual levels of reticence. Luckily, Scotland has excellent public records of births, marriages and deaths, so you can be sure of some facts without having to talk to each other.

I didn’t find out as much as I’d hoped about my immediate family, but I did fill in a few details. I hoped to find a few people who might have photographs, but that hasn’t happened so far. However, I was surprised to be so interested in the lives of people who were so long forgotten.

First I’ll mention some of the websites I used, and then I’ll mention some of the family members that I researched, so that search engines can find their names.

Scotland’s People: Public Records

I’m lucky that almost all my ancestors for several generations lived in Scotland, in Edinburgh or nearby. For some reason, Scotland took excellent records of births, marriages and deaths from 1855 as well as regular census records, and you can search for these records online at scotlandspeople.gov.uk. You can download most of them online, though you need to order some as paper copies – usually the more recent ones. They have some church records from before 1885 too, but these don’t generally include enough detail (such as parents of people getting married) to identify people properly. It’s not awfully expensive.

The Scottish birth certificates, marriage certificates and death certificates include the names of the parents and the professions of the fathers, and the birth certificates include the marriage years too, so you can use them without much doubt. Often, a death certificate will mention the spouse, or be signed by a previously-unknown child or sibling. Sometimes a sibling is the witness for a marriage. Then you can track that person down via birth and death certificates. I don’t know of any other way to find siblings because scotlandspeople.gov.uk doesn’t let you search births by both parents’ names.

The occupations are particularly interesting. For my family they seem to show a move into Edinburgh from surrounding villages at the end of the industrial revolution, moving from menial labour into trades and then the (newly created?) middle class with office jobs. For instance, my great-grandparents and great-great grandparents include several “scavengers” with occasional labourers, bakers, miners, brush makers or factory workers, but some of their (male) children became mechanics or clerks. Their children became clerks and shopkeepers or even doctors.

English Public Records

This is far harder for the English birth, marriage and death (BMD) records. They seem to exist, but they aren’t online, and you can’t even order them easily unless you know the exact place and year. freebmd.org.uk only has an incomplete index, but it looks like you’d have to look through the complete set of BMD microfiches in a major English city to be thorough. This is a huge waste.

For instance, I can’t find the certificate for my aunt’s (Joan Isabel Lawrence) death in London around 1995.

Ancestry.co.uk / ancestry.com / ancestry.de

The Ancestry.com service (or their regional versions) is genuinely useful. They have many (but apparently not all) English records that I wouldn’t have found otherwise, and most of the Scottish records. Most usefully, you don’t need to do individual searches – their Hints system will find possible supporting records for people in your family tree and offer to add new family members that those records mention. However, they don’t have all the Scottish records, so you’ll still need to use scotlandspeople.gov.uk.

They have some other sets of records of varying levels of completeness, such as boat passenger lists, phone books and military service records, which I’ve often found useful.

Likewise, the Hints system lets you expand your tree by using the public family trees from other users. I’ve even found a few photographs of slightly-distant relatives this way. This can tend to offer the illusion of certainty when people accept conclusions that may be based on inadequate records.


I’ve also used 23andme‘s DNA Relatives feature. This is generally full of a thousand 4th or 5th cousins who are far enough removed that it’s almost impossible to see the connection, but I’ve had one 2nd/3rd cousin (and her son) show up. Because I got my father into 23andme too, it could show me that she was related on my mother’s side. She didn’t know much about her family, but she gave me enough clues for me to use scotlandspeople.gov.uk to see that her grandmother was the sister of my mother’s grandmother.

In general, 23andme’s list of possible relatives has not been very useful so far. Most connections that it shows are almost impossible to investigate using public records or family knowledge. Many must be due to unofficial biological fathers or mothers that don’t show up in marriage and birth records.

Most people on 23andme are in America and I have noticed a tendency for them to fixate on proving that they are directly related to settlers from northern Europe, happily ignoring the hundreds of other ancestors who would have been in the same generation. Maybe this will be harder once 23andme has a broader cross-section of even American society.

My Grandfather, Ian Murray Lawrence, and my grandmother, Isabella Forsyth

My grandfather, Ian Murray Lawrence (1914-08-17 to 2006-09-26) lived in Edinburgh but my parents had moved to Swindon, which was around 10 hours away by train at that time. My mother didn’t talk to him. I didn’t meet him often until I was in Edinburgh at University in 1991/1992 and even then he was a wall of silence. My mother, Margaret Maya Lawrence (1944-12-03 to 1999-07-15) died in 1999 and he died in 2006.

He was a pharmacist, as was my mother. My father says his pharmacy was in Pilton, Edinburgh, and the 1950 phonebook on ancestry.co.uk lists him at 33 W(est) Pilton Park, Davidson’s Mains, Edinburgh, near where he lived in Blackhall, Edinburgh. I’d love to find a photograph of it though it was apparently a fairly temporary structure that’s since been replaced with a health center.

My grandfather mentioned once vaguely, while drunk, that he had been in the pacific during World War 2, but never wanted to talk about it. Indeed, my mother’s birth certificate in 1944 mentioned that he was a Sick Bay Petty Officer in the Royal Navy. Now that I’m his next of kin, I could request his service records from the Royal Navy (this works for the Air Force and Army too). The forms are slightly awkward and they only take payment via paper cheque, but after a couple of months they gave me his complete list of postings. They showed that he was mostly at onshore Royal Navy hospitals, starting in Wales and England, but then in Australia and Hong Kong. This is his complete record, in case anyone else with similar results (or photos!) finds it via Google:

1942-12-30 to 1943-02-08: HMS Glendower: Probationary Sick Berth Attendant
1943-02-09 to 1943-02-09: Passage: Probationary Sick Berth Attendant
1943-02-10 to 1943-05-26: RNH Plymouth: Probationary Sick Berth Attendant
1943-05-27 to 1943-06-27: RNH Plymouth: Sick Berth Attendant
1943-06-28 to 1943-09-02: RNH Plymouth: Sick Berth Petty Officer
1943-09-03 to 1944-03-27: HMS Drake: Sick Berth Petty Officer
1944-03-28 to 1944-03-28: HMS Pembroke: Sick Berth Petty Officer
1944-03-29 to 1944-03-29: Passage: Sick Berth Petty Officer
1944-03-30 to 1945-03-05: RNH Chatham: Sick Berth Petty Officer
1945-03-06 to 1945-03-08: HMS Pembroke: Sick Berth Petty Officer
1945-03-09 to 1945-04-09: Passage: Sick Berth Petty Officer
1945-04-10 to 1945-04-14: HMS Golden Hind: Sick Berth Petty Officer
1945-04-15 to 1945-04-30: HMS Furneaux: Sick Berth Petty Officer
1945-05-01 to 1945-09-10: HMS Brisbane: Sick Berth Petty Officer
1945-09-11 to 1945-09-20: HMS Furneaux: Sick Berth Petty Officer
1945-09-21 to 1945-10-10: Passage: Sick Berth Petty Officer
1945-10-11 to 1946-03-22: RNH Hong Kong: Sick Berth Petty Officer
1946-03-23 to 1946-05-29: HMS Pembroke: Sick Berth Petty Officer

My grandfather’s wife, Isabella Forsyth (1915-10-02 to 1996-02-19), was said to have disappeared in the late 1950s or early 1960s, but I went with my mother to her cremation in 1996. I now have her death certificate showing that she died (apparently of suicide) in a (psychiatric?) care home in Edinburgh (since closed). Presumably my grandfather and mother knew all along where she was. I’d like to know when and why she was there, but I don’t think I’m entitled to access to any of her medical records.

I did discover that she had a sister, Margaret Pevey Forsyth (1911-10-26 to 1986-03-13) who had two sons David Shaw and John Shaw- my mother’s cousins. I even found those sons’ children (my second cousins) on Facebook, but there’s no real way to contact strangers on Facebook. Three are in England and one is in Florida. I have a picture of the English 2nd-cousin’s father with my mother, and I do wonder if they have more pictures of my family.

My grandfather’s (Ian Murray Lawrence) father’s death certificate from scotlandspeople.gov.uk was signed by his brother Alexander Lawrence who I’d never heard of. I then found him on the 1911 census (the parents’ ages and father’s profession matched) via ancestry.co.uk, and found his death certificate via scotlandspeople.gov.uk. He died of a heart attack in 1982 on North Bridge in Edinburgh while staying at the Salvation Army hostel at 1 Pleasance. Presumably they couldn’t find any relatives because he was listed in 1982 under “estates fallen to the crown”. My mother apparently had no idea that this uncle existed. So my grandfather seems to have mislaid at least his brother, his wife, and two daughters.

My aunt, Joan Isabel Lawrence

This is still  the biggest family mystery.

I never met my  mother’s sister, Joan Isabel Lawrence (1954-02-09 to approx. 1995) who nobody seemed to have hear of since before I was born. In 1995 we heard that she had died in London of sclerosis of the liver – she’s assumed to have drunk herself to death. But that’s just what my father says that my mother said that my grandfather found out when someone replied to a Christmas card that he sent her. We were surprised that he had an address for her and we don’t know what it was. Apparently it took a few months for them to identify her body and my father thinks she was using the name Joan Maclaren, maybe as a stage or modelling name. The GRO say they can’t find any death certificate for Joan Lawrence, Joan Forsyth (her mother’s maiden name) or Joan Maclaren,for England and Wales for 1994 to 1996.

My grandmother, Isabella Stubbs Sparks

I actually knew my grandmother Isabella Stubbs Sparks (1911-07-10 to 2000-03-10) and grandfather Richard Cummings (1904-06-02 to 1990-02-11) because they moved to London and then to Swindon, where I lived. She was always strange, but now I can see that her family life must have been difficult. The last of 9 children, her parents lost five of her siblings within just a few years, mostly before she was born. In 1903 the 7th child died 3 days after birth. In 1906 the 8th child died after 1 yearof spina bifida. In 1908 the second-oldest died at age 11 from drinking Tuberculosis-infected milk.  In 1914, the 5th child died at age 16. In 1917 the oldest died at age 25 at the Somme in WW1. This cannot have been a happy home.

This is the other major change that I see when looking at the family tree that I built up. People just 2 or 3 generations ago regularly had around 10 children and lost half of them. We forget how lucky we are.

Google Music is a bit Awkward

This is a little addition to my post about building a Heart of Rock and Soul playlist on Google Music.

I’m surprisingly unbothered that I need to use Google Music on an Android device (or iPhone) or web browser to play my music. I mostly use my Android tablet or phone through a bluetooth speaker. However, it could use lots of improvement:

  • There’s no way to export a playlist, and your Google Music data is not part of Google Takeout.
  • I don’t think there’s a way to purchase all the tracks in my playlist. I’m afraid of what would happen if I cancelled my All Access subscription. Would it offer me the chance to buy the tracks? Would it permanently delete my playlist? Would I lose everything before I knew if I would lose everything?
  • You can’t search for tracks in a playlist. The browser’s (Firefox or Chrome) Find feature generally only searches through one page of the playlist.
  • You can’t easily move tracks around. If you want to add a track near the start of a 1000 song playlist then you’ll spend a long time dragging and dropping it from the bottom of the list to the top.
  • In the Google Music Android app, one false touch of the screen during an unexpected screen rotation can cause you to accidentally swipe a song out of your playlist. There’s no way to undo it, and no way to know exactly which version of the track you have just lost.
  • Songs you add to your library (or playlist) today might not play tomorrow. I’ve had songs just refuse to play. I guess the albums were removed from Google Music, but it would be nice to see some onscreen explanation when it happens. I’ve had this happen with Mitch Ryder and the Detroit Wheels’ “Rev Up” compilation, Ann Peebles’ “The Hi Singles A’s & B’s” compilation and a Gene Pitney song.
  • It gets confused sometimes and fails silently. Playlists sometimes won’t sync between different browser tabs, as if the changes haven’t reached the server. Recently my playlist was stuck at 991 songs. Trying to add one more seemed to work, but it didn’t show up in other browser tabs or in the Android app. Trying to move the song in the playlist resulted in a “Couldn’t change order. Please try again.” error message. By chance I found that the playlist in the Android app had some of those now-unplayable songs (see above) in strange positions that were not showing up in the browser. After removing them in the Android app, I could make changes in the browser again.