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.