Cordova: All flavors must now belong to a named flavor dimension.

Messing around with Cordova I stumbled upon the following exception when building the app for Android:

A problem occurred configuring root project 'android'.
> All flavors must now belong to a named flavor dimension. Learn more at https://d.android.com/r/tools/flavorDimensions-missing-error-message.html

The almighty folks over at Stackoverflow suggest to update the build.gradle and add a flavorDimensions parameter into the android section. As this smells like a dirty workaround for an issue that should (as always) not be happening in the first place, I found some deeper digging into this topic from Dave Alden. To sum it up: cordova-android@6.4.0 requires Gradle v4, but cordova-plugin-crosswalk-webview is incompatible with Gradle 4.

This leaves you with 3,5 options:

  • Upgrade cordova-android to 7+: This might mess up all your other plugins as they did some breaking changes (that’s why I still had to stick to 6.4.0). Quite a lot of Cordova plugins are not yet compatible with Cordova v7+ as of today.
  • Downgrade cordova-android even further: This has the risk of some other side-effects, missing stability and security updates, etc.
  • Downgrade Gradle to v3: This might lead to incompatibilities with e.g. cordova-plugin-crosswalk-webview
  • Abandon Cordova altogether and switch to React Native, Xamarin or Weex… but yeah.

Further references

Error Logging for Ionic 2 with Sentry (Raven.js)

Sentry is a realtime, platform-agnostic error logging and aggregation platform, that helps me catch errors across different projects. Raven.js is Sentry’s official browser JavaScript client and supports „quite a few“ technologies and frameworks (like plain-old JavaScript, Node.js: Express, Koa, Connect, Angular.js 1, Angular, Ember, React, Vue,…).

Ionic 2 comes with an excellent Error-Handling by default. It simply smashes all exceptions right into the developer’s face (the „React approach“ to handle things). This in itself is alright for development, but in production you should probably log all exceptions with solutions like Sentry.

To log exceptions with Sentry on Ionic 2, I decided to extend the existing IonicErrorHandler to additionally forward the logs to Sentry. The snippet below gives an example:

import * as Raven from 'raven-js';
import {NgModule, ErrorHandler} from '@angular/core';
import {IonicApp, IonicModule, IonicErrorHandler} from 'ionic-angular';
import {MyApp} from './app.component';
import {FoobarPage} from '../pages/home/home';

Raven
  .config('*YOUR DSN*')
  .install();

class RavenErrorHandler extends IonicErrorHandler implements ErrorHandler {
  handleError(err: any): void {
    super.handleError(err)
    Raven.captureException(err.originalError);
  }
}

@NgModule({
  declarations: [MyApp, FoobarPage],
  imports: [
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [MyApp, FoobarPage],
  providers: [{provide: ErrorHandler, useClass: RavenErrorHandler}]
})
export class AppModule {}

Cordova 5: Building signed Android applications

Even though signing Android applications is quite simpler than signing iOS applications, it’s sometimes annoying to set it up and reliably automate it (without using Phonegap or comparable services). Recently I tried automating singing a Cordova application for Android and struggled finding a reliable documentation.

The official Cordova documentation states, that you can easily append a bunch of arguments to the build command to automatically sign your Android application:

Keystore (--keystore): Path to a binary file which can hold a set of keys.
Keystore password (--storePassword): Password to the keystore
Alias (--alias): The id specifying the private key used for singing.
Password (--password): Password for the private key specified.
Type of the keystore (--keystoreType): pkcs12, jks (Default: auto-detect based on file extension)

The catch is, you need to append these arguments as platformopts (POPTS):

cordova build [PROD] [TARGET] [EXP] [PLATS] [BUILDCONFIG] [-- POPTS]

  PROD:   --debug|--release
  TARGET: --device|--emulator|--target=FOO
  EXP:    --experimental [EXPERIMENTALFLAGS]
  PLATS:  PLATFORM [...]
  BUILDCONFIG: --buildConfig=CONFIGFILE
  POPTS:  platformopts

Therefore the command to build a signed Cordova android application becomes:

cordova build --release android -- --keystore=my.keystore --storePassword=K3ySt0reP4ssw0rd --alias=foobar --password=K3yP4ssw0rd

Alternatively, you could specify them in a build configuration file (build.json) using (–buildConfig) argument.

{
     "android": {
         "release": {
             "keystore": "my.keystore",
             "storePassword": "K3ySt0reP4ssw0rd",
             "alias": "foobar",
             "password" : "K3yP4ssw0rd",
             "keystoreType": ""
         }
     }
 }

and respectively

cordova build --release android --buildConfig=buildConfig.json

I tested all those commands with Cordova 5.4.0