Wednesday, August 29, 2018

Don't try to store references from within FragmentPagerAdapter.getItem

In my app, I have some activities with tab views managed by FragmentPagerAdapters that need to receive notifications from the containing activity. My first strategy was to store a reference to them in an instance variable on the activity class from within the getItem method, between creating the object and returning it. However, this leads to a crash if the screen is rotated. The activity is recreated, but the fragments don't need to be reinstantiated, so getItem isn't called for the rotated activity and the references remain null.

A better way is to override the instantiateItem method on FragmentPagerAdapter. Calling the superclass's implementation will get or create the fragment object, which can be stored in a reference and then returned.

Saturday, August 25, 2018

Android static fields can be reset if the app is backgrounded

An Android app I'm working on uses static fields to store data that it downloads at launch. This was working great during development, but after release I observed a lot of null-reference crashes when accessing those static fields. When Android needs to free memory, it terminates processes belonging to apps that aren't currently visible to the user; when the user resumes the app, Android restores the stack of activities, but the process itself is new. Therefore, static fields get reset.

To fix my problem, I wrote a function that checks whether the static data is gone, and if so, launches the activity responsible for downloading the data. I tweaked all activities that require the static data to call this function before doing anything in onCreate or onStart, bailing out if the function indicates that the data needs to be reloaded. An argument to the intent used to relaunch the loading activity indicates whether the loader should just finish() instead of starting a new instance of the main activity.

Simulating Android background process termination

To free up memory, Android sometimes terminates the processes of apps that are in the background. Therefore, apps need to be able to restore from saved state. To test this from Android Studio:

  1. Open the app in a connected device or emulator
  2. Press the home button to put the app in the background
  3. In the Logcat window in Android Studio, press the Terminate button on the left (might be hidden in a pop-out menu)
  4. Resume the app from the device's Overview menu

Monday, August 20, 2018

New apps will take a little while to appear in Play store search

Today I published my first app to the Google Play store. Despite the status in the Play Console showing as "published," I couldn't find it in the Play store search even though the direct link to the listing from the Play Console worked. Apparently it can take a little while for changes to appear in the search. After a couple hours, I got an e-mail about the IARC rating certificate. The next time I tried, I was able to find my app in the search - not sure if that's the specific trigger though.

Sunday, August 19, 2018

Android APK signing configurations need to be assigned to the build type too

Today I needed to generate a signed APK to test an Android app in the release configuration. Setting the build variant to "release" and trying to run produced an error about needing to sign the APK. So I created a signing configuration on the Signing tab of the Project Structure dialog (where the error message's Fix button took me), but the problem persisted. Apparently the signing configuration also has to be assigned to the build type; this is not done automatically. The build variants listed on the Built Types tab have a Signing Config field - setting that to the newly created Signing entry does the job.

Friday, August 17, 2018

Nested ListViews may not size themselves correctly

One screen in the Android app I'm working on involves a nested ListView. The outer ListView contains instances of a fragment that involves another ListView. Originally I wanted the inner ones to make themselves as large as necessary to contain all their items, but the usual wrap_content height only made them tall enough to show the first item. Nested scrolling didn't seem to work, and even if it did, that would be a poor user experience. Apparently nesting ListViews only displays reasonably if the inner ones have their height specified. I did that by measuring each item and adding up the heights as in this SO answer. One thing to note is that the measuring didn't seem to take into account line-wrapped text, so I had to prevent wrapping by applying android:maxLines="1" to the inner TextViews.

Thursday, August 16, 2018

ConvertTo-Json has a very shallow -Depth by default

PowerShell's ConvertTo-Json cmdlet can turn a hierarchy of objects into a JSON document. By default, though, objects just two reference layers down will be stringified instead of serialized to JSON. This can be adjusted with the -Depth parameter.

FMod - IMF import crash fix

Today I received a bug report from an Abiathar user. He found that importing a certain IMF song using the Song Mappings dialog caused Abiathar to crash. Investigating, we found that just the specific IMF file was corrupt - its header specified far more notes than the file actually contained, so Abiathar unexpectedly hit the EOF when trying to load it all. So Abiathar didn't have so much an IMF handling problem as an error handling one, but obviously it's bad to bring down the entire application when confronted with invalid resources, so I added the appropriate error handling.

Tuesday, August 14, 2018

OpenStreetMap can put addresses on nodes, ways, or relations

I've been fiddling with OpenStreetMap (specifically Overpass Turbo) to get the locations of the addresses/buildings in a region. At first it looked like all the buildings were "ways," which are collections of nodes (points) and can represent buildings as well as roads. So I looked for tags on the ways to identify the structures. Then I noticed that my query didn't pick up some buildings - especially ones that have interior borders (holes) - and found that there are also "relations." Relations seem to be collections of ways, one way per border. They can have the tags to represent buildings too. After I got all that worked out, I noticed that my query was still missing a few places. Some buildings were entered as nodes sitting in the middle of the area that borders the actual building, with tags on that individual node.

Sunday, August 12, 2018

Android ListViews might cut off the last item

I'm working on an Android app and trying to smooth out the UI. One issue I've noticed is that ListViews sometimes get cut off at the bottom of the screen. In my project, this seems to only happen when they fill the entirety of a fragment that's presented as a tab in a tabbed activity. I hear that switching to a RecyclerView fixes this, but filling items in a RecyclerView is more complicated than in a plain ListView. Adding some padding to the bottom of the list (android:paddingBottom="30dp", with more padding if the items are thicker) works as a workaround, but I'm still looking for something more elegant that always works.

Saturday, August 11, 2018

When windows become unresponsive after another program goes fullscreen

I've noticed something interesting on my current installation of Windows 10 that I don't remember seeing before. When one application (DOSBox specifically) went fullscreen, windows belonging to other programs stopped responding to mouse movements or clicks. They can be made normal again by pressing Windows+Down then Windows+Up, thereby restoring and re-maximizing them.

Friday, August 10, 2018

Rearranging the language list with PowerShell

The region/language section of the Settings app allows reordering the language preferences by using the up and down arrows that appear when a language entry is selected. The order can also be changed with PowerShell. The Get-WinUserLanguageList cmdlet retrieves a list. The items can be swapped just like in any other collection, then the revised list can be made the new order with Set-WinUserLanguageList.

Tuesday, August 7, 2018

NTRights will adjust privilege lists even when set by Group Policy

Group Policy Objects can define privilege lists in the User Rights Assignment section. When configured with Group Policy, these lists cannot be changed with the Local Security Policy snap-in on the client machine. I noticed, however, that the NTRights utility (from the Windows Server 2003 Resource Kit) is perfectly happy to adjust the privilege lists anyway. The change is reflected in the Local Security Policy editor, which still won't allow editing the list. More importantly, the change actually takes effect (at the next logon of affected users, like usual). The caveat is that the domain's policy will be reapplied if the client is rebooted or if the responsible GPO is edited.

Monday, August 6, 2018

Forwarding the current cmdlet's arguments to another

One user had a cmdlet that took several parameters (some optional) and wanted to pass all the cmdlet's parameters to a different cmdlet. Their first approach was to use Invoke-Expression. While that is a good way to run a dynamically generated command, there is a simpler method in this case. The call operator supports real bound parameters (not stringified), $PSBoundParameters is a hashtable of the current cmdlet's parameters, and splatting allows using a hashtable as the parameters to a cmdlet. These things together make for a very elegant command:

& $cmdletName @PSBoundParameters

If the calling cmdlet has extra parameters relative to the callee, $PSBoundParameters can be .Clone()'d, then the clone can be edited down and passed on.

Sunday, August 5, 2018

Keen Modding Live - Adjusted version tree in Abiathar Live Studio

My original rendition of the version selection dialog for Abiathar Live Studio assumed that an approved/visible version could never be derived from an unapproved/hidden one. Its call to the "get versions" API supplied the "approved versions only" switch when appropriate, so it didn't even get the hidden versions. (I might either remove that API switch or change it so that a useful tree can be constructed from its response.) I adjusted Abiathar Live Studio's tree generation code to request all versions of the level but cut hidden ones out of the lineage while keeping relationships between approved versions intact, just like the level info page on the web.

Friday, August 3, 2018

Keen Modding Live - Comments unattached to versions

I decided that it would be good to allow comments on Keen Modding Live comments unattached to specific versions, that is, comments made directly from the level page as opposed to a version player page. Once comment notifications (or any kind of notifications at all) become a thing, people will often want to reply to comments on their levels, so the page they get directed to should have reply functionality. The version player page is very heavy (several MB), so I won't want to direct users to a section of that from comment notifications.

So I tweaked the API and database schema to allow leaving the version field null. The timestamp is still recorded, of course, so attentive readers will be able to see whether a comment is obsolete (due to a new version being uploaded) by looking at the date it was posted.

Thursday, August 2, 2018

Stopping a user from deleting a file they own

One person wanted to stop a specific user from deleting their own files from a specific directory while still allowing them to create and edit files. Permissions to delete files are interesting in that either one of these will be sufficient:

  • Delete permissions on the file to be deleted
  • Delete-child permissions on the folder that contains the file to be deleted
Therefore, the permissions on the containing folder and the file need a delete right denied to the restricted user. Since the user owns any files they create and could just change the ACL, an OWNER RIGHTS rule is needed to suppress the default grants.