Tuesday, December 31, 2019

Parceling and unparceling is not necessarily deep cloning

Serializing something to a temporary buffer then deserializing it is often an easy way to duplicate an object that supports serialization. Today I was trying to make independent copies of a handful of different Parcelable classes, so I tried writing a general function to parcel them then read them back out. I ran into trouble with testing because my Robolectric shadows of IBinder classes the parcelables referred to contributed state that did not get written to the parcel. However, I realized another problem: parcels can transfer active IBinder objects. These will be reconstituted into proxies that call into the original object, foiling the plan of creating a deep, independent copy for an arbitrary Parcelable.

Monday, December 30, 2019

Putting an array on the pipeline with the unary comma operator

When output onto the pipeline, PowerShell arrays tend to explode into individual pipeline items. I used to deal with this by passing arrays as parameters instead. Recently, though, I heard about the unary comma operator. Placing a single comma before any value, including an array, produces a single-element array containing the value. When that explodes onto the pipeline, it releases the original array.

Sunday, December 29, 2019

When Android Studio can't open the run configurations dropdown

I was doing some quick testing using a class with a main method in Android Studio, launching it with the run button in the margin, which creates an ad hoc run configuration. I then Refactor | Rename'd the class, at which point an IDE Error occurred, probably because there was suddenly no class with the most recently run name. (I assume the same thing would have happened in IntelliJ.) After this, even trying to pull down the run configurations dropdown to pick a different one didn't work.

To reset the workspace, I had to close Android Studio, delete the workspace.xml file from the .idea directory, and reopen the IDE. That cleared various things including the ad hoc run configurations.

Saturday, December 28, 2019

Getting Logcat output from Robolectric tests

By default, Logcat output (from Log calls) doesn't seem to go anywhere when running tests under Robolectric. To see it, the log stream has to be set:

ShadowLog.stream = System.out;

However, there might be undesired spurious output from Android or third-party components. One way to deal with this would be to set the stream to a custom one that filters the output in some way before writing it to standard out. Alternatively, you could provide a custom ShadowLog implementation that filters by tag or call stack. One of my projects checks to see if the current thread's stack trace has a class in the app's package right before Log. To avoid unnecessary checks, the result on whether the log is "internal" is cached by tag.

Friday, December 27, 2019

Seagate SeaTools can help test other brands of drives

Today I needed to check the health of a drive whose manufacturer doesn't seem to distribute diagnostic software specifically for it. I would have looked over the SMART information with Speccy, but the free version is for home use only and I was working with a business. I had heard good things about Seagate's SeaTools, so I tried that. It was able to perform a handful of checks on the drive which were helpful.

Thursday, December 26, 2019

Jackson KotlinModule signature changed between versions

I'm working with several Gradle plugins that use Jackson for JSON and/or YAML parsing. They're written in Kotlin, so they take advantage of the Jackson Kotlin module. I found after trying to upgrade some plugins' dependencies that Gradle sync always crashed with a NoSuchMethodError regarding the KotlinModule constructor. It appears that that constructor gained a new optional parameter - which changes its JVM method signature - in multiple versions, which is a binary-incompatible change. That makes differences in dependency version very likely to cause crashes. Updating some but not all plugins to 2.10.x causes a problem; 2.9.8 and 2.9.9 seem to be fine.

Wednesday, December 25, 2019

Provided Robolectric shadows can be replaced

Robolectric provides shadows of many Android classes and has a way to register custom shadows. Today I needed more functionality from a shadow that already existed. Fortunately, it seems that any user-provided shadows (registered in robolectric.properties as usual) replace the defaults.

Wednesday, December 18, 2019

When Get-Content doesn't recognize the -Encoding parameter

PowerShell's Get-Content cmdlet can read NTFS alternate data streams either with the -Stream parameter or by putting the stream after a colon in the path. Using the latter approach and trying to get the data of a file in the current directory as a byte array, someone mentioned that they received an error saying "a parameter cannot be found that matches parameter name 'Encoding'". This turned out to be because the path wasn't being interpreted as a file system path because it wasn't qualified - the .\ was missing. So the file system provider wasn't being used, and apparently that provider is responsible for some dynamic parameters like -Encoding. Qualifying the path fixed the problem.

Wednesday, December 4, 2019

When Android Studio says "this project does not use the Gradle build system" in the presence of build.gradle

Today I helped a student who was seeing some strange behavior from Android Studio. The IDE appeared to be mostly working, but compilation failed with errors about being unable find several items that all happened to be provided by a library.

Opening the project produced a "Migrate to Gradle" suggestion stating that "this project does not use the Gradle build system." Accordingly, there was no File | Sync Project with Gradle Files menu item. The project had been created as a Gradle project. I was shown screenshots that confirmed the existence and contents of all expected build.gradle files, which was very confusing because the migration suggestion appeared even after clearing all caches I could think of.

Staring very intently at the screen eventually revealed a subtle problem: the parent directory of the project had been opened, not the project itself. Since there was no build.gradle in the opened root directory, Android Studio rightfully did not consider it a Gradle project, but allowed setting the Android SDK manually (which is what the student must have done to be able to attempt compilation). Opening the correct location in the directory hierarchy fixed the problem.