Monacaアプリ、ひいてはCordovaアプリを開発していて避けては通れないのが、「Cordovaプラグイン」の存在です。

スマートフォンの機能(例えば、カメラのエフェクト、アプリ内課金など)を使おうと思った時、Web技術だけでは限界があります。そうした時にWeb技術とネイティブの橋渡しをしてくれるのが、「Cordovaプラグイン」になります。

「Cordovaプラグイン」は、すでに数千種類も作成されているので、大抵の場合はこの中から選べば十分でしょう。しかし、AndroidやiOSのバージョンアップによって動かなくなったり、新しい機能がまだプラグインがない場合もあります。そうした時に備え、自分でプラグインの作り方を学んでおくのは大事です。

この記事では、最も基礎的なプラグイン作成法を紹介します。

このプラグインでは、バッテリーの残量を取得するという処理を行っています。

基本形

まず最初にディレクトリを作成します。

$ mkdir my-cordova-plugin

この中に package.jsonplugin.xml というファイルを作成します。
さらに、 srcwww というディレクトを作ります。

そして、 src の中に androidios というディレクトリを作成します。
構造は、次のようになります。

$ tree
.
├── package.json
├── plugin.xml
├── src
│   ├── android
│   └── ios
└── www

package.jsonplugin.xml は、Cordovaプラグインに必要な情報です。元々は plugin.xmlだけでしたが、最近は npm(Node.jsのパッケージ管理) でインストールできるようになったので、package.json が追加されています。

src は、ソースコードが入るディレクトリです。 androidはAndroid用、iosはiOS用のソースコードが入ります。

package.json について

例えば、package.jsonは次のようになります。プラグインに関する説明が殆どです。

{
  "version": "0.0.1",
  "name": "cordova-plugin-battery",
  "description": "Cordova Battery Plugin",
  "cordova": {
      "id": "cordova-plugin-battery",
      "platforms": [
          "android",
          "ios"
      ]
  },
  "keywords": [
      "cordova",
      "battery",
      "cordova-android",
      "cordova-ios"
  ],
  "engines": []
}

plugin.xmlについて

plugin.xmlでは、各プラットフォーム(Android/iOS)ごとに設定を記述します。対象のファイルであったり、Androidであれば必要な権限を記述します。詳しくは、コメントを参考にしてください。

<?xml version="1.0" encoding="UTF-8"?>
<!-- プラグインのIDを記述。バージョンをpackage.jsonと合わせておく -->
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
  id="io.monaca.plugin.battery" 
  version="0.0.1">

    <!-- プラグイン全体に関する設定 -->
    <name>BatteryPlugin</name>

    <!-- プラグインの説明 -->
    <description>Battery Plugin</description>

    <!-- プラグイン作成者 -->
    <author>Atsushi Nakatsugawa</author>

    <!-- ライセンス -->
    <license>MIT License</license>

    <!-- 対応Cordovaのバージョン -->
    <engines>
      <engine name="cordova" version=">=3.5.0" />
    </engines>

    <!-- アプリ側で呼び出すJavaScriptファイル名 -->
    <js-module src="www/battery.js" name="battery">
        <clobbers target="Battery" />
    </js-module>

    <!-- iOS用の設定 -->
    <platform name="ios">

      <!-- config.xmlに対する設定があればここに記述 -->
      <config-file target="config.xml" parent="/*">
        <feature name="CVBatteryPlugin">
          <param name="ios-package" value="CVBatteryPlugin"/>
        </feature>
      </config-file>

      <!-- 対象のソースコード -->
      <source-file src="src/ios/CVBatteryPlugin.swift" target-dir="src/ios" />
    </platform>

    <!-- Android用の設定 -->
    <platform name="android">

      <!-- config.xmlに対する設定があればここに記述 -->
      <config-file target="res/xml/config.xml" parent="/*">
        <feature name="CVBatteryPlugin">
          <param name="android-package" value="io.monaca.plugin.CVBatteryPlugin"/>
        </feature>
      </config-file>

      <!-- AndroidManifest.xmlに対する設定があればここに記述 -->
      <!-- 主に権限に関する設定を記述します -->
      <config-file target="AndroidManifest.xml" parent="/*">
        <uses-permission android:name="android.permission.BATTERY_STATS" />
      </config-file>

      <!-- 対象のソースコード -->
      <source-file src="src/android/io/monaca/plugin/CVBatteryPlugin.java" target-dir="src/io/monaca/plugin" />
    </platform>
</plugin>

iOS側のコード

iOSでは、 Swift が使えるようになったので、これまでのように .h/.m ファイルで分ける必要がなくなりました。今回の例のように、バッテリー残量を取る場合、次のようなコードになります。

import Foundation
import UIKit

@objc(CVBatteryPlugin) class CVBatteryPlugin: CDVPlugin {
    // JavaScriptに公開する関数名を記述
    @objc(status:)
    func status(command: CDVInvokedUrlCommand) {
      // バッテリーの残量を取得
      UIDevice.current.isBatteryMonitoringEnabled = true
      let bLevel:Float = UIDevice.current.batteryLevel
      // 返却するレスポンスを作成
      let result = CDVPluginResult(status: CDVCommandStatus_OK,
                                   messageAs: String(bLevel))
      // コールバック形式でレスポンスを返却
      self.commandDelegate!.send(result, callbackId: command.callbackId)
    }
}

Android側のコード

Androidでは、従来通り Java を使います。工夫すると Kotlin が使えるようですが、 Java を使う方が簡単でしょう。

Javaの場合、 src/android/io/monaca/plugin/CVBatteryPlugin.java
といった具合にディレクトリを作成してコードを置くのが基本になるでしょう。

package io.monaca.plugin;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.json.JSONArray;
import org.json.JSONException;
import android.content.IntentFilter;
import android.content.Intent;
import android.os.BatteryManager;
import android.content.Context;

public class CVBatteryPlugin extends CordovaPlugin {
    // Androidは必ずexecuteが呼び出されます
    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        // actionにJavaScriptで呼び出したメソッド名が入るので、必要に応じて処理分岐します
        IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        // バッテリーの残量の取得
        Context context = this.cordova.getActivity().getApplicationContext();
        Intent batteryStatus = context.registerReceiver(null, ifilter);
        int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
        int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
        float bLevel = level / (float)scale;
        // コールバック形式でレスポンスを返却
        callbackContext.success(String.valueOf(bLevel));
        return true;
    }
}

JavaScriptについて

アプリから呼び出すJavaScriptは、 www/battery.js として作成します。これは plugin.xml で指定したパスになります。 cordova.exec を使うのは基本ですが、その呼び出し方は自由です。例えば、以下はコールバック形式での例です。

const Battery = function() {};

Battery.prototype.status = function(success, fail, args) {
  cordova.exec(success, fail, "CVBatteryPlugin","status", args);
};

const battery = new Battery();
module.exports = battery;

アプリから呼び出す際には、次のようになるでしょう。

Battery.status(level => {/* バッテリーの残量*/}, err => { /* エラー */ })

使い方について

Cordovaプラグインができあがったら、Cordovaプラグインの管理からアップロードします。

方法としては、2つあります。

  • プラグイン全体をZip圧縮
  • アップロードしたファイルのURLを指定

後は、Monaca上でアプリをビルドすれば使えるようになります。

テストについて

開発時のテストは、ローカルコンピュータにCordovaコマンドをインストールし、ローカルで実行しながら行うのがいいでしょう。その場合、XcodeやAndroid Studioのブレークポイントが利用できます。

まとめ

自分でCordovaプラグインを作るか否かに関わらず、仕組みを知っておけば、動作を掘り下げて調べる時にも役立ちます。ネイティブの言語を知る必要はありますが、小さなプラグインであれば、コードリーディングもそれほど大変ではないはずです。

プラグインを使うことで、皆さんのアプリがより魅力的になるでしょう。ぜひプラグイン開発にもトライしてみてください。

ユーザー Cordova プラグイン | Monaca Docs