GDG-Philly and Philly Cocoa’s “State of Mobile Union” Event

This week the GDG-Philadelphia group that I manage collaborated with the Philly Cocoa group to run our first in-person event since Covid. The number of folks who showed up was much higher than I thought they would, I think everyone just really wanted to meet each other IRL again.

The developer meetups in the city have unfortunately not re-emerged from Covid as much and I am hoping they do. I am hopeful that more such events start happening again.

Thanks to Kotaro for leading so much of the organization effort for this event, and to Comcast Labs and the Lift Labs group for sponsoring the space and food.

And of course the speakers:

Looking forward to the next one 👋

Some gotchas when using Firebase Dynamic Links

The last couple of weeks I have been trying to add Firebase Dynamic Links into an app and it took me way longer than I had originally planned. In this post, I wanted to share some of the lessons learned.

First: note that there are 2 kinds of links that you can use:

  1. Dynamic links that you generate on the Dynamic Links section of your Firebase project. These will be the same for every user and are great to link to universally same sections of your app. These are quick to set up and are probably a good idea to try before generating the second kind of deep links
  2. Dynamic links generated by a user for another user on a client application. These would be custom links only relevant for unique users and so cannot be generated via the project dashboard.

In my case, I was trying to get #2 working and it proved to be a real bear.

The problem is that when generating a unique URL, you are essentially doing a couple of handoffs: The first link is managed completely by Firebase (usually with a *.page.link URL). This link checks to see if the app is installed on the device the link is launched on and links to the app-install page if not. If that is fine, the link redirects to the second link that you actually are trying to get to. The second link is often a web address on your own domain which needs to be correctly configured for that page, or else the link will just open that webpage which is probably not what you want to do.

Gotcha 1: [Android] Make sure you have the SHA256 signature saved in your Firebase project

For the longest time, I didn’t realize that I had only the SHA1 key saved in my project. Deep links don’t work without SHA256 values for your project. Thanks to this answer from StackOverflow.

It took me a while to get this document correctly deployed (mostly my fault). I really should have read the documentation on verified site associations on Android more carefully. You can verify your assetlinks setup via this URL (just replace the domain and, if applicable, port values):

https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site=https://domain1:port&relation=delegate_permission/common.handle_all_urls

Also remember, if you are using Google Play Store to sign and release your app, your assetlinks should refer to their key’s SHA256 signatures. Conveniently, you can copy the assetlinks file from the Play Store itself under the Setup > App Integrity section of the developer console

Gotcha 3: [Android] Make sure “autoverify” attribute in your intent-filter is set to true

Not sure how I missed this but, this took a long time to find

 <intent-filter android:autoVerify="true">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
     <category android:name="android.intent.category.BROWSABLE" />
     <data
          android:scheme="https"
          android:host="my.app.com" />
 </intent-filter>

iOS:

Surprisingly, as frustrating as getting the Android version to work was, the iOS integration was much simpler. Just following this video helped a lot!

Hope some of this info helps you if you are using dynamic links in your app

Flutter: Efficiently loading images between animations

I was recently playing with Flutter’s PaletteGenerator library. The library does what Android’s Palette API does: gives you a palette of colors based on a bitmap given.

The experience I was going for was to use the dominant color from an image to color the detail screen when the user tapped on it.

It’s fairly easy to use the library if you have a handle on the ImageProvider or the Image object.

getDominantColor(ui.Image img, Function(PaletteColor) onColor){
  if(img == null) return;
  PaletteGenerator.fromImage(img).then((PaletteGenerator g){
    onColor(g.dominantColor);
  });
}

Most of the examples I have seen for PaletteGenerator use an in-app image that the system can immediately load but using remote images is more complicated since the library has to wait for enough of the image to load to read the color data. This gets further complicated if you need to run an animation while loading the image.

After trying a number of iterations, the best approach seems to be using Flutter’s precacheImage method before kicking off the animation

await precacheImage(NetworkImage(b.image), context);

Also, consider using the CacheImage library to improve later performance if that screen is loaded multiple times

Suddenly, Flutter

I had no plans to learn Flutter in 2019

When I first heard of Flutter last year, I couldn’t help but draw parallels to Java Swing, the UI technology I started with in grad school (and thankfully dropped a year or so later). If you don’t know much about Java’s UI technologies, suffice to say that for all of Java’s strengths, no version of their UI framework was ever one of them.

It started okay-ish enough with Java’s AWT toolkit that let Java call native code to create system windows, buttons etc, but devs soon realized that building cross-platform applications (which was always Java’s pitch) was really hard when you could only target the least common denominator widgets that were available across all platforms. “No more” said the Java community, and proceeded to build Swing, a cross-platform UI framework that emulated the system controls by drawing them itself on a canvas.

Image result for write once debug everywhere java

Sound familiar? That was what Flutter promises with the core graphics engine that would emulate the native Android and iOS widgets

The problem is that Swing turned out to be crap. The widgets never felt native and performed poorly. You could always tell if you were using a Swing app. And it was always interesting when some app wasn’t coded right and you’d end up with apps emulating the Windows look-and-feel on a Mac (who checked on a Mac back in those days)

So Flutter was on my “no-thanks” list. Besides my lack of faith in faking native system widgets, the language they chose was Dart! Who knew Dart? More importantly, where were the interesting libraries in Dart? Having done a few React Native apps before, I liked my options with JavaScript and the dream of making cross-platform (mobile AND web) apps.

But then a couple of things happened. One: I saw some pretty compelling Flutter based apps. The interesting thing was, the best apps try to create their own design language anyway, so deviating from the system look-and-feel felt okay; and then second: I tried Flutter for a labweek project and was won over by the one click deploy to multiple platforms and the hot reload (it might also have been just fortuitous timing as I was losing my mind with React Native’s minimal support for custom views and animations, something that Flutter promises a lot more control over)

So for the last 4 months or so I have been working with Flutter and I have to say I really enjoy it. Some parts are definitely rough (I still don’t love the indentation hell when describing layouts) but Dart is enjoyable and is very inspired by the best parts of JavaScript and Swift (among others). Recent additions to Dart have been very interesting, because they address issues in real-world UI development. This feels different from the more generic “Lets create a general purpose language and allow it for UI dev” approach of other languages.

But the core reason I am excited about Flutter is the culture. The reason Swing was a dud (IMHO) was that it was built by people who didn’t care to push UI experiences. The native mobile toolkits are better but still make it hard to build complex user interfaces (SwiftUI and Jetpack Compose are trying to change that). Example “Hello World” apps you see using native toolkits are pretty generic form-based apps.

But look at the kinds of apps Flutter shows off:

Image result for flutter timeline app

🤩

While this may not be everyone’s cup of tea, this “think-outside-boxy-layouts” approach has my vote.

4 months in, I am still new-ish to Flutter but I guess I am on board. Stay tuned for more random Flutter stuff on this blog 🙂