React Native 0.62 and Flipper

In this post AndrΓ©as Hanss gives us a tour on Flipper.

Flipper is a platform for debugging iOS, Android and React Native apps. Visualize, inspect, and control your apps from a simple desktop interface.

To add flipper support to your React Native project, I recommend the β€œAdd Flipper Support” section from the Upgrade to React Native 0.62 guide.

Flipper – Extensible mobile app debugger →
React Native 0.62 and Flipper Will Change Your Mobile Development Experience and make it easier! →

πŸ’΅ This linked article is stuck behind Medium’s metered paywall, which may prevent you from reading it. Open the link in an incognito window to bypass Medium’s ridiculous reading limit.

Paper Phone – A printable paper phone which helps you take a break from your digital world

Nice experiment by Google:

A lot of people feel that they spend too much time on their phones and struggle to find a balance with technology. Paper Phone helps you have a little break away from your digital world by printing a personal booklet of the key information you’ll need that day.

Paper Phone →

Hermes, a JavaScript engine optimized for running React Native on Android

Interesting announcement from Facebook:

Hermes is an open-source JavaScript engine optimized for running React Native apps on Android. For many apps, simply enabling Hermes will result in improved start-up time, decreased memory usage and smaller app size. At this time Hermes is an opt-in React Native feature, and this guide explains how to enable it.

Here’s a side-by-side comparison recording by @nparashuram of one and the same app . The one of the left is with Hermes, the one on the right without:

To enable Hermes, simply edit your android/app/build.gradle file and set enableHermes to true (requires React Native 0.60.2 or newer):

project.ext.react = [
    entryFile: "index.js",
    enableHermes: true  // clean and rebuild if changing
]

One cd android && ./gradlew clean later and you’re good to go πŸ™‚

Hermes Source (GitHub) →
React Native: Enabling Hermes →

Automatically create an APK from your Progressive Web App with PWA2APK

As mentioned in How to publish your PWA onto the Google Play Store it’s now possible to publish your PWA’s onto the Google Play Store.

Thanks to PWA2APK you no longer need to manually create your APK: β€œjust” enter the URL of your PWA and an APK – which you’ll need to publish manually – will be created from it.

This is a tool that Google themselves should’ve created.

PWA2APK – Convert any PWA (Progressive web app) to Google Play Ready Apps →

How to publish your PWA onto the Google Play Store

Thanks to the Trusted Web Activity feature in Chrome 72 on Android, the Google Play Store is now open for Progressive Web Apps.

Chrome 72 for Android is now shipping from the Play Store to all users and this version included Trusted Web Activity (TWA), that in a nutshell is a way to open Chrome in standalone mode (without any toolbar or Chrome UI) within the scope of our own native Android package.

The easiest way to get your PWA published onto the Google Play Store is to clone the example repository and adjust the manifestPlaceholders settings in app/build.gradle.

Additionally you’ll also need to set up Digital Assets Links in /.well-known/assetlinks.json which is hosted on the website also hosting the PWA.

UPDATE 2019-02-12: Thanks to PWA2APK you can now automatically generate a .apk for you to upload to the Play Store.

Google Play Store now open for Progressive Web Apps 😱 →
SVGOMG / Trusted Web Activity Example (GitHub) →
Google Digital Assets Links →

Upgrading from React Native 0.53.x to 0.57.4 (and to Xcode 10 and Gradle 4 along with that), a journey

Back in November, after 6 months of working on other projects, I picked up development for the EV-Point Mobile App again. The app is built using React Native and is available on both iOS and Android.

As Xcode got a new major release (from Xcode 9 to Xcode 10) since my last time working on the project I figured I’d trigger a new build on Bitrise, then see which errors would came at me, and continue from thereon. What I didn’t know however is that it would eventually take me 3 days, 17 failed builds, lots of Google Fu, and some guesswork to get everything working again. Here’s an overview of the biggest hurdles that I had to take, along with their solutions. I hope they might help you too.

There’s always a green light at the end of the build-pipeline tunnel …

My initial plan was to first get the current version of the app – still running React Native 0.53.3 – to build again in Xcode 10, and only then upgrade the React Native version to the latest one (0.57.4 at the time of writing). During the course of my journey I eventually flipped that around, as React Native 0.57.x already contained some fixes that I was in need of.

πŸ‘‹ I’m using Bitrise for automatically building all my apps. If you sign up through this referral link, we both get extra build-time: https://app.bitrise.io/users/sign_up?referrer=09c28434a5e3e18d

~

Problem #1: iOS: React Native project won’t build on Xcode 10

Of course my first Bitrise trigger using Xcode 10 would fail (but one can always try, right?). What I didn’t expect is that quite a lot of things were going wrong (REF):

  • Xcode Signing Issues
  • Failures indicating that libfishook.a could not be linked
  • Third party things such as glog that were not installed
  • etc.

As I stumbled from one build error into the other (locally, of course) and tried fixing these one by one, I eventually found that the most easy solution would be to upgrade to the latest RN version (0.57.4 at the time of writing) as it already contained most of the fixes.

Solution #1 (part1): Upgrading to the latest RN version

To upgrade to the latest RN version I used react-native-git-upgrade. I didn’t immediately jump from RN 0.53 to RN 0.57 though, but gradually went through all intermediate releases.

# install react-native-git-upgrade
yarn global add react-native-git-upgrade

# Go to project folder
cd ~/repos/evpoint/mobileapp/

# Upgrade to RN 0.54.4
react-native-git-upgrade 0.54.4

# Upgrade to RN 0.55.4
react-native-git-upgrade 0.55.4

# Upgrade to RN 0.56.1
react-native-git-upgrade 0.56.1

# Upgrade to RN 0.57.4
react-native-git-upgrade 0.57.4

Using react-native-git-upgrade to upgrade RN versions works like a charm, but it might will require you to resolve a few merge conflicts …


Upgrading from one React Native version to the other …

Once I performed all upgrades I tried building my app locally and … yes, great succes!

πŸ’β€β™‚οΈ Note that when upgrading from RN 0.53 to 0.57, the Android build system will have migrated from Gradle 3 to Gradle 4. As we’re now focussing on getting iOS to build, we’ll skip this for now and tackle it later (see Problem #4 below)

Solution #1 (part2): Manually installing the third party scripts

UPDATE: This is fixed with the release of React Native 0.57.5 (#277c19c). You can skip this step if you’re running 0.57.5 or newer.

After successfully building locally I pushed my changes online in order for Bitrise to kick into action. Bitrise however failed. Hmmz …

- Build input file cannot be found: `./node_modules/react-native/Libraries/WebSocket/libfishook.a`
- `configure: error: in `(..._/node_modules/react-native/third-party/glog-0.3.4'`
- `βœ— Build input file cannot be found: 'node_modules/react-native/third-party/double-conversion-1.1.6/src/strtod.cc'`
- `No member named '__rip' in '__darwin_arm_thread_state64'`

Turns out that there was an issue with third party scripts not getting installed correctly. Locally they were, however.

FYI: Locally it worked fine because – as it turns out – a second build would correctly struggle through it. As Bitrise always starts from scratch (e.g. with a non-existing node_modules folder) it couldn’t make it through.

To fix this I added an extra step in the build-pipeline to Manually install Third Party Scripts + Configure Glog, (REF):

#!/usr/bin/env bash -e

if [ ! -d "node_modules/react-native/third-party" ]; then
  cd node_modules/react-native ; ./scripts/ios-install-third-party.sh ; cd ../../
  cd node_modules/react-native/third-party/glog-0.3.5/ ; ./../../scripts/ios-configure-glog.sh ; cd ../../../../
fi

I’ve added this step right before Bitrise’s Certificate and Profile Installer step.

πŸ’‘You’ll also need to execute this step locally, especially when starting from scratch. You can safely add this script to your local build-script as it contains a built-in check to not double install the Third Party Scripts in case they are already present.

~

Problem #2: Android: Program type already present: android.support.v4.app.ActionBarDrawerToggle$DelegateProvider

On Android I was still getting build errors though. My first one was something like this:

Error:Program type already present: android.support.v4.app.ActionBarDrawerToggle$DelegateProvider

java.lang.NoClassDefFoundError: Failed resolution of: android/support/v4/animation/AnimatorCompatHelper;
java.lang.NoSuchFieldError: No field notification_template_lines of type

Solution #2: Fixate the SDK version for com.android.support to a specific version

Thankfully someone else had already stumbled onto this problem and provided a fix: fixate the SDK version for com.android.support to version 24.2.1. You can do this by adjusting your app/android/build.gradle file:

android {

    …

    // Fix for "Program type already present: android.support.v4.app.ActionBarDrawerToggle$DelegateProvider"
    configurations.all {
        resolutionStrategy.eachDependency { DependencyResolveDetails details ->
            def requested = details.requested
            if (requested.group == 'com.android.support') {
                if (!requested.name.startsWith("multidex")
                        && !requested.name.startsWith("exifinterface")) {
                    details.useVersion '24.2.1'
                }
            }
        }
    }

}

~

Problem #3: Android: Unable to find a matching configuration in project

When running ./gradlew assembleDebug I could successfully build for Android. Running ./gradlew assembleRelease however, yielded this error:

Unable to find a matching configuration of project :react-native-devsettings-android:
  - Configuration 'debugApiElements':
      - Required com.android.build.api.attributes.BuildTypeAttr 'preview' and found incompatible value 'debug'.
      - Found com.android.build.api.attributes.VariantAttr 'debug' but wasn't required.
      - Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
      - Required org.gradle.usage 'java-api' and found compatible value 'java-api'.
  - Configuration 'debugRuntimeElements':
      - Required com.android.build.api.attributes.BuildTypeAttr 'preview' and found incompatible value 'debug'.
      - Found com.android.build.api.attributes.VariantAttr 'debug' but wasn't required.
      - Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
      - Required org.gradle.usage 'java-api' and found incompatible value 'java-runtime'.
  - Configuration 'releaseApiElements':
      - Required com.android.build.api.attributes.BuildTypeAttr 'preview' and found incompatible value 'release'.
      - Found com.android.build.api.attributes.VariantAttr 'release' but wasn't required.
      - Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
      - Required org.gradle.usage 'java-api' and found compatible value 'java-api'.
  - Configuration 'releaseRuntimeElements':
      - Required com.android.build.api.attributes.BuildTypeAttr 'preview' and found incompatible value 'release'.
      - Found com.android.build.api.attributes.VariantAttr 'release' but wasn't required.
      - Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
      - Required org.gradle.usage 'java-api' and found incompatible value 'java-runtime'.
	at org.gradle.internal.component.model.AbstractDependencyMetadata.selectConfigurationUsingAttributeMatching(AbstractDependencyMetadata.java:46)
	at org.gradle.internal.component.model.LocalComponentDependencyMetadata.selectConfigurations(LocalComponentDependencyMetadata.java:90)
	at org.gradle.internal.component.local.model.DslOriginDependencyMetadataWrapper.selectConfigurations(DslOriginDependencyMetadataWrapper.java:60)
	at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.EdgeState.calculateTargetConfigurations(EdgeState.java:143)
	... 89 more

Solution #3: Use matchingFallbacks

The fix was to adjust the defined buildType of debug so that it falls back to the release‘s buildType values in case one is missing. This can be done by using the matchingFallbacks instruction inside your app/android/build.gradle file (REF, REF):

android {

    …
    buildTypes {
        release {
            …
        }
        preview {
            …
            matchingFallbacks = ['release', 'debug']
        }
    }

}

~

Problem #4 Android: Execution failed for task ':react-native-config:verifyReleaseResources'

The final Android problem I encountered was that dependencies would not properly compile anymore with the change to Gradle 4. Packaged like react-native-config and react-native-devsettings-android would fail on their verifyReleaseResources step.

Solution #4: Upgrade packages and/or force subprojects to use same compileSdk/BuildTools as main project

Thankfully packages like react-native-config have already landed fixes for this issue. Merely upgrading your affected dependencies using yarn will fix it.

If you’re using packages do not yet have fixes – like react-native-devsettings-android (ISSUE) – you can thankfully force them to use the correct compileSdk/BuildTools version from within your own android/build.gradle file (REF, REF):

subprojects {
    …

    // Force subprojects to use same compileSdk/BuildTools as main project
    afterEvaluate {project ->
        if (project.hasProperty("android")) {
            android {
                compileSdkVersion rootProject.ext.compileSdkVersion
                buildToolsVersion rootProject.ext.buildToolsVersion
            }
        }
    }

}

~

Furthermore I have a few classic issues – such as signing certificates that were expired – which I had to tackle. Supposedly the release of RN 0.58 – which I’m looking forward to – should no longer require the adjustment mentioned above.

Did this help you out? Like what you see?
Thank me with a coffee.

I don't do this for profit but a small one-time donation would surely put a smile on my face. Thanks!

β˜•οΈ Buy me a Coffee (€3)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

Fix for the Android Emulator (Android Simulator) crashing during launch

UPDATE 2017.08.03: This should be fixed with the release of HAXM 6.1.1. Make sure you’re running the latest version of Android Studio

On a recent project I was working on, I wasn’t able to start the Android Emulator/Simulator anymore from within Android Studio. Every time I launched it from Android Studio it would start, but then – without any errors or warnings – close all by itself.

When I switched to launching the Android Emulator from the Command Line instead, I finally got to see an error message:

$ cd $(dirname $(which emulator)) && ./emulator -avd Nexus_5X_API_25
emulator: WARNING: encryption is off
Hax is enabled
Hax ram_size 0x60000000
HAX is working and emulator runs in fast virt mode.
Failed to sync vcpu reg
Failed to sync vcpu reg
Failed to sync vcpu reg
Failed to sync vcpu reg
Failed to sync vcpu reg
Failed to sync HAX vcpu contextInternal error: Initial hax sync failed

Aha, a clue! One Google Search Coupon later it turns out the thing preventing the emulator from running was that other thing using vcpu’s, namely docker.

πŸ‘‰ Killing docker will let you run the Android Emulator without any problems.

I haven’t tested other suggested solutions (such as tweaking the settings of the virtual device), but at least this one did it for me.

Did this help you out? Like what you see?
Consider donating.

I don’t run ads on my blog nor do I do this for profit. A donation however would always put a smile on my face though. Thanks!

β˜•οΈ Buy me a Coffee ($3)

Launching the Android Emulator from the Command Line

I’m not sure which update exactly broke it, but recently I got this when trying to launch the Android Emulator from the CLI:

$ emulator -list-avds
Nexus_5X_API_25

$ emulator -avd Nexus_5X_API_25
[140735953220544]:ERROR:./android/qt/qt_setup.cpp:28:Qt library not found at ../emulator/lib64/qt/lib
Could not launch '../emulator/qemu/darwin-x86_64/qemu-system-i386': No such file or directory

Apparently there’s some relative path linking happening, which of course fails when running the emulator command from a project directory.

The fix is to run the emulator command from the directory in which it resides. Some command combinations later, this is the result (with Nexus_5X_API_25 being the name of the created virtual device):

cd $(dirname $(which emulator)) && ./emulator -avd Nexus_5X_API_25

UPDATE 2017-11-28: As mentioned by Piotr in the comments below, another way to fix it, is to include the path of the emulator binary in your $PATH environment variable.

If installed correctly, you will most likely find some references to $ANDROID_HOME in your .bash_profile. Below that block, add this line to it:

export PATH="$ANDROID_HOME/emulator:$PATH"
Did this help you out? Like what you see?
Consider donating.

I don’t run ads on my blog nor do I do this for profit. A donation however would always put a smile on my face though. Thanks!

β˜•οΈ Buy me a Coffee ($3)

Jasonette – Build cross-platform mobile apps using JSON

Just like how web browsers turn HTML into a web page, Jasonette turns JSON into iOS native components. This lets you build native apps by writing a simple JSON.

Here’s a small snippet/example:

{
    "$jason": {
        "head": {
            "title": "{ ΛƒΜ΅Μ‘α΄₯Λ‚Μ΅Μ‘}",
            "offline": "true",
            "actions": {
                "$foreground": {
                    "type": "$reload"
                },
                "$pull": {
                    "type": "$reload"
                }
            }
        },
        "body": {
            "header": {
                "style": {
                    "background": "#ffffff"
                }
            },
            "style": {
                "background": "#ffffff",
                "border": "none"
            },
            "sections": [
                {
                    "items": [
                        {
                            "type": "vertical",
                            "style": {
                                "padding": "30",
                                "spacing": "20",
                                "align": "center"
                            },
                            "components": [
                                {
                                    "type": "label",
                                    "text": "It's ALIVE!",
                                    "style": {
                                        "align": "center",
                                        "font": "Courier-Bold",
                                        "size": "18"
                                    }
                                }
                            ]
                        },
                        {
                            "type": "label",
                            "style": {
                                "align": "right",
                                "padding": "10",
                                "color": "#000000",
                                "font": "HelveticaNeue",
                                "size": "12"
                            },
                            "text": "Check out Live DEMO",
                            "href": {
                                "url": "http://www.jasonbase.com/things/xXQ"
                            }
                        },
                        {
                            "type": "label",
                            "style": {
                                "align": "right",
                                "padding": "10",
                                "color": "#000000",
                                "font": "HelveticaNeue",
                                "size": "12"
                            },
                            "text": "Watch the tutorial video",
                            "href": {
                                "url": "https://www.youtube.com/watch?v=S7yGejKIH6Q",
                                "view": "Web"
                            }
                        }
                    ]
                }
            ]
        }
    }
}

The JSON is fetched over HTTP, and then loaded into your app:

This declarative way of working reminds me of one of the approaches I took at work whilst building Culture Club Magazine. Next to the default Story Item types (Cover, Teaser, Article, List, etc.) – each with their specific properties – there’s also a story item type named Custom which accepts a declarative list of components (along with their style, animations, and actions). That list is then translated to actual React components which get rendered inside the story item itself πŸ™‚

Jasonette →
Build cross-platform mobile apps using nothing more than a JSON markup →

Animating vectors in Android with AnimatedVectorDrawable

Seeing Lottie in action, I was reminded of Android’s AnimatedVectorDrawable which also allows one to do vector based animations.

This class animates properties of a VectorDrawable with animations defined using ObjectAnimator or AnimatorSet.

If you’re familiar with SVG, the AnimatedVectorDrawable XML contents will look familiar.

The β€œEndless Pin Jump” animation (pictured above) for example is something that can be animated using AnimatedVectorDrawable. Like SVG you can write your XML manually, or use an IDE – such as AndroidIconAnimator (web-based) – to creating your AnimatedVectorDrawables. Online tools to convert your SVGs to the VectorDrawable format also exist πŸ™‚

An Introduction to AnimatedVectorDrawable
Animation: Jump-through using AnimatedVectorDrawable
β€œEndless Pin Jump” animation with AnimatedVectorDrawable
AndroidIconAnimator, web-based AnimatedVectorDrawable IDE →
SVG to VectorDrawable convertor →