WeetA

Quand normalement rime avec rarement !

Plugin GeoLocation 0.0.8 de NativeScript qui ne fonctionne pas sur iOS 9+

Comment perdre plusieurs heures à comprendre comment fonctionne un produit ?
En utilisant un de ses plugins buggy :)
Avant d'expliquer le problème, je tiens à dire que je débute en NativeScript.
Après avoir créé une pauvre application avec un champ text, un label et un bouton, je me suis dit comme beaucoup : "Tiens ! je vais jouer avec la position GPS"
Super, c'est bien expliqué dans la partie Hardware Access > Location de la documentation.
En gros, il faut ajouter le plugin avec la commande :

tns plugin add nativescript-geolocation

Puis, dans le fichier xml de l'UI, j'ai ajouté 2 boutons :

  • 1 pour demander l'autorisation d'accès à la position
  • 1 pour récupérer la position
<Button text="Enable Location" tap="enableLocationTap"/>
<Button text="Get Current Location" tap="getLocationTap"/>

Côté JS, il faut ajouter le code associé aux boutons :

var geolocation = require("nativescript-geolocation");
function enableLocationTap(args) {
    if (!geolocation.isEnabled()) {
        geolocation.enableLocationRequest();
    }
}
exports.enableLocationTap = enableLocationTap;

function getLocationTap(args) {
    var location = geolocation.getCurrentLocation({desiredAccuracy: 3, updateDistance: 10, maximumAge: 20000, timeout: 20000}).
    then(function(loc) {
        if (loc) {
            console.log("Current location is: " + loc);
        }
    }, function(e){
        console.log("Error: " + e.message);
    });
}
exports.getLocationTap = getLocationTap;

C'est parti, on pousse l'appli sur le iDevice à coup de :

tns run ios --release

Impec, l'appli se lance. Un petit Tap sur Enable Location et là ... rien, quedal, nada. Bon ! ça aurait dû me demander l'autorisation d'accéder à ma position.
Un petit Tap sur Get Current Location et là ...

CONSOLE LOG file:///app/main-page.js:40:20: Error: Location service is disabled

Je vous passe les Tap, reTap, rereTap, compile, clean, raahhh, plugin remove/add, platform remove/add, recherches google, github, ... rien.
J'ai cherché un peu du côté des accès demandés pour l'appli (comme les manifest Android). C'est rangé dans le fichier Info.plist.
Après vérification sur la page Cocoa Keys, les clés NSLocationWhenInUseUsageDescription et NSLocationAlwaysUsageDescription sont bien présentes.
Faut chercher ailleurs. Le plugin ne sera pas buggy ? non quand même, ça serait vraiment la loose !
Commençons par le fichier suivant qui parait, d'après son nom, bien être celui qui nous intéresse :

node_modules/nativescript-geolocation/nativescript-geolocation.ios.js

J'y retrouve notre fonction enableLocationRequest. Et là, j'ai compris. Il y a un test de version iOS 8 strict au lieu d'un test de version minimum.
J'ai oublié de vous le dire mais vous l'avez peut-être vu dans la page Cocoa Keys, les clés NSLocationWhenInUseUsageDescription et NSLocationAlwaysUsageDescription ne sont prises en charge qu'à partir de iOS 8. Avant, il fallait utiliser l'unique clé NSLocationUsageDescription.
J'ai modifié le code comme suit :

 function enableLocationRequest(always) {
-    if (platformModule.device.osVersion.indexOf("8") === 0) {
+    var intOsVersionMajor = parseInt(platformModule.device.osVersion.split('.')[0]);
+    if (intOsVersionMajor >= 8) {

Après recompilation et exécution, ça fonctionne comme prévu. Cool !
Du coup, j'ai créé un incident sur le GitHub de NativeScript pour que ce soit corrigé dans une future version : iOS 9+ Location Request does nothing

Crash au lancement des applications NativeScript en mode debug

Lorsque l'on utilise une des commandes suivantes de NativeScript 1.5.2 pour exécuter une appli sur un iDevice 64bits (iPhone 6 par exemple), l'application se lance et crash immédiatement.

$ tns debug ios
$ tns deploy ios
$ tns run ios

Le log d'Application Crash sur le iDevice remonte une exception EXC_BAD_ACCESS (SIGBUS)

Date/Time:           2016-01-29 09:23:33.45 +0100
Launch Time:         2016-01-29 09:23:32.42 +0100
OS Version:          iOS 9.2.1 (13D15)
Report Version:      105

Exception Type:  EXC_BAD_ACCESS (SIGBUS)
Exception Subtype: KERN_PROTECTION_FAILURE at 0x0000000015d0e070
Triggered by Thread:  0

Filtered syslog:
None found

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   ???                             0x15d0e070 0 + 366010480
1   CoreFoundation                  0x2759096b 0x274e7000 + 694635

Par contre, aucun soucis lorsque le projet est compilé directement depuis Xcode.

Le problème est connu et référencé dans le thread Crash when launching applications on iPhone 6 in debug mode #1362.

Il semblerait qu'en mode debug, la CLI de tns compile uniquement en armv7 contrairement à Xcode qui compile en arm64.

Ce sera corrigé dans l'ios-runtime 1.6.0.

En attendant le seul workaround pour compile via la CLI est d'ajouter le paramètre --release

$ tns debug ios --release
$ tns run iOS --release

 J'ai volontairement omis tns deploy --release car la commande retourne le message suivant:

When producing a release build, you need to specify all --key-store-* options.

Sauf que ces options ne sont pas dispos pour ios :) Ce problème est également connu et référencé (tns deploy ios --release command prints incorrect message. #1403)

Erreur Cordova après mise à jour en version 6.0.0 via npm sur Mac

Cordova 6.0.0 vient juste de sortir (https://cordova.apache.org/news/2016/01/28/tools-release.html). C'est parti pour une petite mise à jour via npm.

$ sudo npm install -g cordova@latest

La mise à jour s'est bien déroulée mais cordova ne fonctionne plus trop bien comme le montre le message d'erreur suivant:

MyAppliFolder$ cordova -v
module.js:341
    throw err;
    ^

Error: Cannot find module 'umask'
    at Function.Module._resolveFilename (module.js:339:15)
    at Function.Module._load (module.js:290:25)
    at Module.require (module.js:367:17)
    at require (internal/module.js:16:19)
    at Object.<anonymous> (/usr/local/lib/node_modules/cordova/node_modules/npm/lib/utils/umask.js:1:75)
    at Module._compile (module.js:413:34)
    at Object.Module._extensions..js (module.js:422:10)
    at Module.load (module.js:357:32)
at Function.Module._load (module.js:314:12) at Module.require (module.js:367:17)

Que faire ? Supprimer Cordova et le re-installer.

$ sudo npm uninstall -g cordova
$ sudo npm install -g cordova@latest

Voila, c'est nettement mieux :)

MyAppliFolder$ cordova -v
6.0.0