カテゴリーアーカイブ JavaScript

asaba 著者:asaba

【cordova】unable to load platformAPIでブラウザが開けなかった時の解決法

今回は再びコルドバの話題に戻ります。

先日cordovaを7.0.1から8.0.0にアップデートした時のことです。

直後にブラウザで動きを試したいと思い、いつものようにコマンドでnpm run serveでブラウザを実行したところ、下記のエラーが出現しました。

コルドバのバージョンをcordova.jsやモジュールにも認識させないといけなかったみたいです。

browserのplatformを入れ直したところ一発で解決しました。

一旦rmで消して↓


cordova platform rm browser

addで追加します


cordova platform add browser

ちなみに他のplatformを消す必要はないのでそこは大丈夫です。

一応このエラーの解決はしましたが、以前chromeで開けてたアプリがIEで表示されるようになってしまいました。原因は調査中です。

解決方法が見つかり次第このブログに書いていきたいと思います。

 

 

  • この記事いいね! (0)
著者:杉浦

assertで想定外の動作のみを検知する

 デバッグを行う際、プログラム中の変数、式を追うことになります。この変数や式を全て画面に出力すると読む対象が多すぎてとても分かりにくいです。また徐々に異常な結果を辿って、変数や式をその都度画面に出力する場合、実行回数がかさみ時間がかかってしまいます。assert文は異常を発見した時にのみ知りたい変数や式を出力させるための文です。またこのassert文はユーザに見せる本番環境の際には消えている必要があります。assert文の実行は実行速度の低下であり、assert文の出力は脆弱性の発見のきっかけにもなります。
 大体のassert文はassert(条件文,出力定義の色々)という呼び出され方をします。条件文の評価結果がtrueの場合、出力はされず、falseの場合、出力がされます。assert(想定の動作の際の条件文, Errorの際に知ると役に立つであろう値)と書くと想定外の動作を整った情報と共に検出し、早く修正できます。かくあるべし、と意味を書く際のコメントの代わりにもなります。
Console.assert() – Web API インターフェイス | MDN
 javascriptのassetは次の様に使えます。

console.assert(条件式,出力したいものA,出力したいものB,出力したいものC,...)

 出力は次の画像のconsole.log(出力したいもの)と同じ様に表示されます。  javascritptでは外部でどうにかすることでassertを見せないようにします。一つは力技の様な気がしますが

Object.keys(console).forEach(key => {console[key] = () => {}})

の実行です。これによってブラウザの持つconsoleオブジェクトの持つ要素を全て空の関数で埋めます。これならば結果は表示せず、実行速度の面でもconsoleなしより少々遅いぐらいで済みます。ただしユーザはconsoleを使うためにconsoleの再定義が必要になり、また再定義された場合、consoleの中身が表示されてしまいます。もう一つはbabel-plugin-transform-remove-console – npmをつけたbabelのようなconsoleを除去するコンパイラを通すことによってコード内からassert文を消すことです。javascriptの実行コードはユーザがダウンロードするファイルです。そのため高速化を目的にソースコードを結合、圧縮します。その時にまとめてassertの除去を実行することで手間を意識せずassertを消せます。

PHP: assert – Manual
 PHPのassertは7前後で異なっています。PHP7では次のように簡単に書けます。

<?php
$a = 2;
$b = 1;
// assertionを作成
assert($a < $b);
assert($b < $a, '$b is less than $a.$a:'.$a.' $b:'.$b);
assert($a < $b, '$a is less than $b.$a:'.$a.' $b:'.$b);

実行結果

<br />
<b>Warning</b>:  assert(): assert($a &lt; $b) failed in <b>[...][...]</b> on line <b>5</b><br />
<br />
<b>Warning</b>:  assert(): $a is less than $b.$a:2 $b:1 failed in <b>[...][...]</b> on line <b>7</b><br />

 assert(条件式,出力文字列)とするだけです。出力文字列とassert文を記述した行数を出力してくれます。出力文字列を指定しない場合はfalseを出力した条件文を出力します。
 PHP7より前のバージョンではコールバックの指定が必要であり少々面倒です。

<?php
// assertを有効にし、出力を抑制する
assert_options(ASSERT_ACTIVE, 1);//assert()による評価を有効にする。0でassert()を読み飛ばす。
assert_options(ASSERT_WARNING, 0);
assert_options(ASSERT_QUIET_EVAL, 1);

// ハンドラ関数を作成する
function my_assert_handler($file, $line, $code, $desc = null)
{
    echo "Assertion failed at $file:$line: $code";
    if ($desc) {
        echo ": $desc";
    }
    echo "\n";
}

// コールバックを設定する
assert_options(ASSERT_CALLBACK, 'my_assert_handler');

// 失敗するassertionを作成
assert('2 < 1');
assert('2 < 1', 'Two is less than one');

実行結果

Assertion failed at [...][...]:21: 2 < 1
Assertion failed at [...][...]:22: 2 < 1: Two is less than one

 PHP7より前では必ず評価を行った状態を引数にしたコールバックを呼び出します。これが手間で昔のassert文はあまり使われなかったらしいです。PHP7はコールバック呼び出しも可能なまま、容易に使えるasset文になりました。
 PHPはオプションで宣言することによってassert文を読み飛ばします。PHP7ではphp.ini中にzend.assertions=-1とすることでassert文を読み飛ばせます。PHP7より前ではassert_options(ASSERT_ACTIVE, 0);とすることでassertによる評価を無効にします。

  • この記事いいね! (0)
著者:杉浦

javascriptの静的解析ツールESLint

ESLint – Pluggable JavaScript linter
 ESLintはjavascriptのためのlintです。lintはプログラムが動作不能になるような致命的な文法エラーのみならず様々なものを発見する目的で使用されます。発見したいものは例えば、間違いを犯しやすい記述であるアンチパターン、インデントの乱れのようなコードスタイルのぶれ、です。ESLintの特長は次の様な拡張性にあります。

  • すべての検証ルールを自由にon/offできる
  • 260個以上(5.5.0時点)の豊富なルールがある

  •  この特長のため自分のプロジェクトに合わせたカスタムルールを簡単に作ることができます。また、ECMAScript 2015 (ES6), 2016, 2017, 2018, 2019を標準サポートしており、新しくなった記法を使う様に自身を矯正することもできます。
     ESLintはnpmで導入できます。
    eslint – npm
     installはプロジェクトのルートをcdにして次のコマンドを実行です。

    npm install --save-dev eslint

     同じくプロジェクトのルートに.eslintrc.jsonを置いて、以下の記述を書き込んで簡単な初期設定が完了です。

    {
        "extends": ["eslint:recommended"],
        "parserOptions": {},
        "env": {"browser": true},
        "globals": {},
        "rules": {}
    }

     実行は

    eslint src/js

    のみです。これでsrc/js以下がeslintにかけられます。
     
     上述した通り、eslintには多数のルールがあります。その一つ一つを管理するのは手間です。そのためまずはextendsでルールセットを継承します。ここではeslintのおすすめにしてありますが、プラグインとして様々な設定が公開されています。googleなんかも公開しています。
     parserOptions,env,globalsには実行環境の構文なり、ライブラリなりを書き込みます。これを設定しないと問題が無いにも関わらず、グローバル変数、関数を宣言していない、その構文は成り立たない、と怒られます。

    //設定例
        "parserOptions": {
            "ecmaVersion": 2018
        },
        "env": {
            "browser": true,
            "es6": true,
            "jquery": true
        },
        "globals": {
            "L": false,
            "google": false,
            "cloneLayer":false
        },
    

     eslint src/jsを実行した際にsrc/js/lib以下にライブラリが入っているとなるとeslintがライブラリにも怒り始めます。.eslintignoreという設定ファイルでこれを制御できます。書き方は色々なignoreファイル同様、対象に含みたくないファイルのパスを羅列するだけです。

    **/lib/*

     eslintにかけた対象が既存のコードであったり、一気に組み立てた初期のコードであったりする場合、大量のerrorとwarningが出力されます。そしてその大半はいちいち手作業で直すのが嫌になる様な手間な部分です。–fixオプションを付けることでインデント、クォート、セミコロンの様な単純なミスをeslint側で修正してくれます。

    eslint src/js --fix
    • この記事いいね! (0)
    村上 著者:村上

    【Cordova】FCMによるプッシュ通知のアイコンが白い四角になるときの対処法

    調べていたのは別の症状についてだったのですが、これも有益そうだったので、備忘録としてまとめ。
    Cordovaで開発中のアプリに、FCM(Firebase Cloud Messaging)を利用したプッシュ通知機能を追加したのですが、Android端末に送られてきた通知のアイコンに指定した画像が反映されず、単なる四角形になってしまったときの対処法について。

    参考にさせていただいたサイトはこちらから。

    IonicでFCMによるpush通知を行う – Qiita
    https://qiita.com/saihoooooooo/items/34712738d5cc6f03cdf4

    また、使用しているプラグインはこちらです。

    GitHub – fechanique/cordova-plugin-fcm: Google FCM Push Notifications Cordova Plugin
    https://github.com/fechanique/cordova-plugin-fcm

     

    で、対処法ですが、そもそも原因はアイコン画像が指定されていないか、指定方法が間違っているのが原因です。
    そのため、下記の場所にそれぞれアイコンを保存します。

    • platforms/android/res/mipmap-ldpi
    • platforms/android/res/mipmap-mhdpi
    • platforms/android/res/mipmap-hdpi
    • platforms/android/res/mipmap-xxhdpi
    • platforms/android/res/mipmap-xxhdpi
    • platforms/android/res/mipmap-xxxhdpi

    そして、config.xml で、下記のようにアイコンの指定を行います。

    <platform name="android">
        <resource-file src="resources/android/fcm_push_icon/drawable-ldpi-icon.png" target="res/mipmap-ldpi/fcm_push_icon.png" />
        <resource-file src="resources/android/fcm_push_icon/drawable-mdpi-icon.png" target="res/mipmap-mdpi/fcm_push_icon.png" />
        <resource-file src="resources/android/fcm_push_icon/drawable-hdpi-icon.png" target="res/mipmap-hdpi/fcm_push_icon.png" />
        <resource-file src="resources/android/fcm_push_icon/drawable-xhdpi-icon.png" target="res/mipmap-xhdpi/fcm_push_icon.png" />
        <resource-file src="resources/android/fcm_push_icon/drawable-xxhdpi-icon.png" target="res/mipmap-xxhdpi/fcm_push_icon.png" />
        <resource-file src="resources/android/fcm_push_icon/drawable-xxxhdpi-icon.png" target="res/mipmap-xxxhdpi/fcm_push_icon.png" />
    </platform>
    

    なお、厳密にこのとおりでなくても良いようなので、ファイル名などは適宜変更してください。

    あとは、送信時のJSONデータに、アイコンと色を指定すればOKです。

    {
      "to": [デバイストークン],
      "priority": "high",
      "notification": {
        "icon"  : [アイコン画像],
        "color" : [色コード],
        "title" : [アプリ名],
        "body"  : [メッセージ],
        "sound" : "default",
      }
    }
    

    …が、私の環境ではまだ直っていないので、きっとどこかにミスがあります…。
    恐らくですが、アイコン画像の場所とかが怪しいかな。

     

    以上、Androidでプッシュ通知にアイコン画像が反映されていない時の対処法でした。
    意外とこういう小さな箇所って、だからこそ目についたりするので、気を付けたいですね。

    • この記事いいね! (0)
    著者:杉浦

    webページ評価ツールLighthouse

     Lighthouse – Chrome ウェブストア
     Lighthouse によるウェブアプリの監査 | Tools for Web Developers
    | Google Developers

     Lighthouseはwebページの評価を行ってくれるツールです。お手軽な使い方は上記リンクのウェブストアからChrome拡張機能としてのLighthouseを導入し使用することです。オプションもコマンドも必要なく、ただ起動するだけで監査を行い、結果を出力します。 Lighthouseの評価は下図の様にPerformance,ProgressiveWebApp,Accessibility,Best Practices,SEOに分かれています。

     それぞれ、Performanceはおおよそ速度、データ量関連に問題が無いか、ProgressiveWebAppはネイティブアプリのようにふるまえるか、Accessibilityはわかりやすさ、Best Practicesは良いとされるやり方をしているか、SEOは検索エンジン最適化がされているか、です。画像の更に下の方には細分化された指摘がいくつもあります。
     Lighthauseの特徴は、googleが奨励しているPWAとしての評価がgoogle自身の規定でできる、という点です。またSEOは大概眉唾物ですが検索エンジン大手のgoogleが提供するツールが評価するSEOですから多少は当てになるでしょう。
     これが高得点ならばよいwebページというわけはないです。PWAは特に顕著でアプリである必要のないページは多々あります。基本的にぱっと見の第一印象がどうか、という点から評価がなされます。ただ高得点のページならば低得点のページよりも快適に使用しやすいのではないでしょうか。
     また、Lighthouseの指摘により今まで知らなかったより良いやり方を知ることもできます。

    • この記事いいね! (0)
    著者:杉浦

    letとvar

     let – JavaScript | MDN
     letはECMAScript2015で標準化された記法のひとつです。上のリンク先には下の様に記述されています。

    let 文はブロックスコープの局所変数を宣言します。任意で値を代入して初期化できます

     具体的にどういうことかというと下図の様な感じです。varはブロックスコープ内部でvarを付けて再宣言しても別の変数として扱ってくれません。一方でletは再宣言をすれば別の変数と扱ってくれます。

     もちろん、宣言なしなら同じ変数として扱ってくれます。

     特に役に立つのは次の様な実行タイミング毎の処理です。
    参考:varよりすごいletとconst。(現代的JavaScriptおれおれアドベントカレンダー2017 – 02日目) | Ginpen.com
     

     javascriptのsetTimeout()は、コールバックの実行を待機して、タイミングが合ったらコールバックを実行、それ以外の部分は待機関係なしに続行、という処理を行います。setTimeoutの待機後のコールバックで使用される変数の値が待機中に変更されたら、待機を始めた時の値ではなく、その変更された値を参照して実行を行います。varの場合、スコープがループ全体にかかっているため、変数iはすべて同じ変数です。そのため、ループ終了後の値である5のみが表示されました。一方でletはループ毎に異なる変数として扱われます。そのため0,1,2,3,4と順々に表示されました。i++は次のループのlet iに渡す値の決定に関わるのみで、今のループのiを変更していない感じ

    • この記事いいね! (0)
    著者:杉浦

    javascriptのコンパイラであるbabelの紹介

    Babel · The compiler for next generation JavaScript
     javascriptはES6という便利な記法があります。これから先も少しずつ記法が増え、javascriptプログラムをより楽に正確に書くための言語も増えていくでしょう。しかしながら、ブラウザにこれら全てを生のまま対応しろというのは酷な話です。javascriptのみでも未対応の関数、記法は少なからずあります。babelは近年の多様な言語を多くのブラウザで読めるようにコンパイルしてくれるプログラムです。
     具体的に何ができるかというと

    a => b
    let d = `d`;
    const e = `e`;
    `abc${d}
    ${e}
    `
    class Point {
        constructor(x, y) {
            this.x = x;
            this.y = y;
        }
        distance() {
            return Math.sqrt(this.x * this.x + this.y * this.y);
        }
    }
    new Point(1, 2)
    

    こんなのが

    var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
    
    function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
    
    (function (a) {
        return b;
    });
    var d = "d";
    var e = "e";
    "abc" + d + "\n" + e + "\n";
    
    var Point = function () {
        function Point(x, y) {
            _classCallCheck(this, Point);
    
            this.x = x;
            this.y = y;
        }
    
        _createClass(Point, [{
            key: "distance",
            value: function distance() {
                return Math.sqrt(this.x * this.x + this.y * this.y);
            }
        }]);
    
        return Point;
    }();
    new Point(1, 2);
    

     こんなのになります。後者の文量は前者の5倍以上です。classは元々のjavascriptになかっただけあってとても巨大になっています。この記述の変換によって、便利な記法で書いたjavascript用プログラムがIEでも難なく動きます。Try it outのでブラウザ上のままお試しが出来ます。
     babelはnpmで導入できます。installはプロジェクトのルートをcdにして次のコマンドを実行。

    npm init
    npm install --save-dev @babel/core
    npm install --save-dev @babel/preset-env
    npm install --save-dev babel-cli
    npm install --save-dev babel-core
    npm install --save-dev babel-preset-minify
    

     同じくプロジェクトのルートに.babelrcを置いて、以下の記述を書き込んで簡単な初期設定が完了。

    {
    "presets": [
      ["env",{
        "targets": {
          "browsers": ["last 2 versions", "ie 11"]
        },
        "modules": false,
        "useBuiltIns": true
      }],
      ["minify",{
        "keepFnName": false,
        "keepClassName": false
      }]
    ]}
    

     minifyの設定があるように圧縮もできます。他にも設定可能な項目は多々あります。
    使いかたは次の通り、次のコマンドでsrc以下がdist以下にコンパイルされます。

    babel src -d dist

     一度準備さえすればそこからは楽の積み重ねができます。

    • この記事いいね! (0)
    村上 著者:村上

    【Cordova】QRコードリーダーを実装するプラグイン「phonegap-plugin-barcodescanner」

    今回はCordovaで開発しているアプリに、QRコードリーダーの機能を実装する方法について。
    コードがかなり分かりやすかったのでおすすめのプラグインです。
    使用したプラグインは「phonegap-plugin-barcodescanner」。
    phonegap という名前が付いていますが、Cordovaでも問題なく使えます。

    GitHubはこちらから。

    GitHub – phonegap/phonegap-plugin-barcodescanner: cross-platform BarcodeScanner for Cordova / PhoneGap
    https://github.com/phonegap/phonegap-plugin-barcodescanner

     

    早速実装方法ですが、まず下記のコマンドでプラグインを追加します。

    cordova plugin add phonegap-plugin-barcodescanner
    

    プラグインの追加が終ったら、config.xml を確認します。
    もし、下記の1行が追加されていなかったら追加してください。

    <preference name="android-build-tool" value="gradle" />
    

    また、iOSの場合は、info.plist に 「Privacy – Camera Usage Description」の項目を追加しないと、アプリからカメラが起動できないので、こちらも追加します。
    設定はこのくらいです。

    あとは、下記のコードを記述するだけです。

    cordova.plugins.barcodeScanner.scan(
        function (result) {
            // QRコードの読み込み成功
            // 成功時の処理
            // Result: result.text
            // Format: result.format
            // Cancelled: result.cancelled
        }, 
        function (error) {
            // 読み込み失敗
            // 失敗時の処理
        }
    );
    

    上記のコードが実行されると、自動的にカメラを使用するかを尋ねるダイアログが表示され、許可を選択すると、画面内に四角形が表示されているQRコードリーダーが起動します。
    で、カメラを適当に作成したQRコードにかざしたところ、無事コード内の情報を取得できました。

    ちなみに、試しに作ったQRコードは、本記事のアイキャッチ画像でも使用しています。
    なお、取得できるのはこのブログのURL https://cpoint-lab.co.jp/です。
    このURLは、上記のコードでは、result.text で取得できます。
    適当なコードが見つからない場合は、是非ご利用ください。

     

    以上、CordovaアプリでQRコードリーダー機能を実装する方法でした。
    最初はカメラを扱うということで、難しいのでは…と思っていましたが、実装が楽なプラグインのおかげでかなり簡単でした!
    もし似たようなことを行いたいとお考えでしたら、是非ご参考にしてください。

    • この記事いいね! (0)
    村上 著者:村上

    【Cordova】iBeaconを扱うための「cordova-plugin-ibeacon」が動作しない時の対処法

    先日投稿した、「【Cordova】アプリでiBeaconを扱うための「cordova-plugin-ibeacon」が動作しない【未解決】」という記事の、解決策が見つかりました…!
    解決策というより、原因はコードに一部抜けがあったせいなんですけどね!

     

    早速ですが、正常に動作したコードはこちら!

        // 位置情報を取得
        cordova.plugins.locationManager.requestWhenInUseAuthorization();
        cordova.plugins.notification.local.registerPermission(function (granted) {
            // console.log('Permission has been granted: ' + granted);
        });
    
        // delegateの作成と設定
        var delegate = new cordova.plugins.locationManager.Delegate();
        delegate.didDetermineStateForRegion = function(pluginResult) {
            console.log('didDetermineStateForRegion', pluginResult);
        }
        delegate.didStartMonitoringForRegion = function(pluginResult) {
            console.log('didDetermineStateForRegion', pluginResult);
        }
        
        // ビーコンを検知している間呼ばれる
        delegate.didRangeBeaconsInRegion = function(pluginResult) {
            document.getElementById("rangeDiv").value = JSON.stringify(pluginResult);
        }
        
        // ビーコンをキャッチ
        delegate.didEnterRegion = function(pluginResult) {
        }
    
        // ビーコンの範囲外に移動
        delegate.didExitRegion = function(pluginResult) {
        }
    
        // delegate の設定
        cordova.plugins.locationManager.setDelegate(delegate);
    
        // 監視するビーコンの設定
        var uuid = '00000000-1d4e-1001-b000-001c4dbec041';
        var identifier = 'ibeacon';
        var major = 1;
        var minor = 3;
        var beaconRegion = new cordova.plugins.locationManager.BeaconRegion(identifier, uuid, major, minor);
        beaconRegion.notifyEntryStateOnDisplay = true;
    
        // 監視の開始
        cordova.plugins.locationManager.startRangingBeaconsInRegion(beaconRegion)
            .fail(function(e) { console.log(e); })
            .done();
        cordova.plugins.locationManager.startMonitoringForRegion(beaconRegion)
            .fail(function(e) { console.log(e); })
            .done();
    

    変更点は、49行目の下記の記述を追加した点です。

    cordova.plugins.locationManager.startRangingBeaconsInRegion(beaconRegion)
        .fail(function(e) { console.log(e); })
        .done();
    

    様々なサンプルコードを見比べたところ、ここの記述が不足していました。
    で、コードを追加したところ、問題なくビーコンの信号を取得できました!
    というわけで、ただの私のポカミスだったわけです。
    …凡ミスで恥ずかしい限りです。
    今後は気を付けなければいけませんね。

     

    ということで、以上、iBeaconを扱うための「cordova-plugin-ibeacon」が動作しない時の対処法でした。
    可能であれば、きちんと動作するサンプルコードを改変してアプリ開発を行った方が安全かもしれません。

    • この記事いいね! (0)
    村上 著者:村上

    【Cordova】JavaScript上のConsole.log()をXcodeのデバッグエリアに表示する方法

    以前からCorodvaアプリを開発していましたが、最近になって便利なプラグインを発見したのでご紹介。
    というか、何故これを開発初期に入れていなかったのか…ちょっと後悔しています。

     

    おすすめしたいプラグインは「cordova-plugin-console」です。
    タイトルにもあるように、こちらのプラグインを導入すると、JavaScript上で記述した console.log() などの結果を、Xcodeのデバッグエリアに表示させることができます。
    なお、参考にさせていただいたサイトはこちらから。

    Cordova アプリの console.log() を XCode に出力する cordova-plugin-console – Corredor
    http://neos21.hatenablog.com/entry/2017/07/10/080000

    そして、GitHubのリンクはこちらから。

    GitHub – apache/cordova-plugin-console: Apache Cordova Plugin console
    https://github.com/apache/cordova-plugin-console

    導入方法は、下記のコマンドを実行するだけ。

    cordova plugin add cordova-plugin-console
    

    あとは、devicereadyイベントの後に console.log() を記述すれば、それがデバッグエリアに表示されます!
    また、試してはいませんが、Android Studio でも同様に使えるそうです。

     

    以上、Console.log() をXcodeのデバッグエリアに表示する方法でした。
    プラグインの導入だけなので、かなり簡単に行えます!

    今まで alert() をメインで使ってきて、そこまで不便は感じていなかったのですが…やはりできるとかなり楽ですね。
    Cordovaアプリの開発者はぜひインストールをご検討ください。

    • この記事いいね! (0)