はじめに
こんにちは、@rs_tukkiです。
12月にラクスのAdvent CalenderでCordovaについての記事を寄稿しましたが、今回もCordovaについての話をさせていただきます。
Cordovaとは?
さて、まずはCordovaについて軽く触れておきます。
Cordova(Apache Cordova)とは、オープンソースの開発フレームワークです。
平たく言えばSpring Framework等と似たようなものです。
Cordovaの特徴は、同じソースコードで、Android、iOS、ブラウザの3つのプラットフォーム向けにアプリのビルドができることです。
いわゆる「クロスプラットフォーム」というやつです。
また、基本的にHTML/CSS/Javascriptで動作するため、バックエンドの知識に明るくないエンジニアでも単純なアプリケーションの開発であればできてしまうのもメリットです。
Cordova Pluginを自分で作ってみる
先ほど「(Cordovaは)基本的にHTML/CSS/Javascriptで動作する」と書きました。
基本的に、というのは文字通り基本的な動作しか実現できないという意味で、AndroidやiOS特有の機能、例えばカメラなんかにアクセスすることはそのままではできません。
そこでどうするかというと、JavaScriptからJavaやSwiftのコードを呼び出して使えるようにするわけです。
こういったネイティブ特有の機能を呼び出すためのコード群を「Cordova Plugin」といいます。
Cordova自体はかなり成熟したフレームワークですから、主要なネイティブ機能はApache公式がプラグインを整備していたりしますし、
Githubを漁ってみればそれこそCordovaユーザが独自に開発したプラグインが山のように見つかります。
ただし、そういった第三者の作成したプラグインはあまりメンテナンスされていないものが多く、最終更新が3年前、4年前といったものもザラです。
使いたい機能のためのCordovaプラグインを見つけた!と思ったらろくにアップデートもされておらずエラーになって使用できない……というのはよくある話。
そのようなプラグインはフォークして自分でメンテナンスしてもいいですが、折角なので0から自分でプラグインを作成するやり方を学んでみましょう。
Cordovaプロジェクトの作成
Cordova Pluginを作成する前に、まずは土台となるCordovaプロジェクトを作成します。
npm installでCordovaをインストールしたら、cordova create [プロジェクト名]
でテンプレートを作成してくれます。便利。
$ sudo npm install -g cordova Password: + cordova@11.0.0 added 129 packages from 59 contributors, removed 36 packages, updated 125 packages and moved 2 packages in 15.838s $ cordova create testApp Creating a new cordova project. $
Cordovaプロジェクトの作成直後は、以下のようなツリー構造になっています。
$ tree . ├── config.xml ├── package.json └── www ├── css │ └── index.css ├── img │ └── logo.png ├── index.html └── js └── index.js 4 directories, 6 files
www
ディレクトリがCordovaで画面表示や画面遷移を実現するための核となる部分です。
これだけでも最低限アプリは動くようになっていますが、今回はAndroid向けのCordovaプラグインを実装して、
「今開いているアプリがdebugビルドかどうか」を判定できるようにしてみましょう。
先に結論から言ってしまうと、プラグインの実装後は以下のようなツリー構造になります。
$ tree . ├── config.xml ├── package.json ├── plugin │ └── cordova-plugin-checkIsDebug │ ├── package.json │ ├── plugin.xml │ ├── src │ │ └── android │ │ └── CheckIsDebugPlugin.java │ └── www │ └── checkIsDebugPlugin.js └── www ├── css │ └── index.css ├── img │ └── logo.png ├── index.html └── js └── index.js 10 directories, 11 files
Pluginの定義(plugin.xml / package.json)
まずは、Cordovaプラグインを利用するために必要な設定を記載していきます。
まずはファイル全体をぺたり。
<?xml version="1.0" encoding="UTF-8"?> <plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" id="cordova-plugin-check-is-debug" version="1.0.0"> <name>Check is Debug Plugin</name> <description>check whether cordova app is debugMode</description> <author>rs_tukki</author> <license>MIT License</license> <engines> <engine name="cordova" version=">=7.0.0"/> </engines> <js-module src="www/checkIsDebugPlugin.js" name="pluginBridging"> <clobbers target="checkIsDebug" /> </js-module> <platform name="android"> <config-file target="res/xml/config.xml" parent="/*"> <feature name="CheckIsDebug"> <param name="android-package" value="com.rs.tukki.testapp.plugin.checkisdebug.CheckIsDebugPlugin"/> </feature> </config-file> <source-file src="src/android/CheckIsDebugPlugin.java" target-dir="com/rs/tukki/testapp/plugin/checkisdebug/" /> </platform> </plugin>
Plugin.xmlではこのプラグインの名前やバージョン、どのようにそのプラグインを呼び出すかといった情報を定義しています。
特に重要なのは<engines>
、<js-module>
、<platform>
の各ディレクティブです。
では一つづつ解説していきます。
<engines> <engine name="cordova" version=">=7.0.0"/> </engines>
<engines>
ディレクティブでは、このプラグインを使用するのに要求されるCordovaのバージョンを指定できます。
省略しても問題ない項目ではありますが、あまりにも古いCordovaを使用していると使えないケースもありますので、ひとまず7.0辺りを指定しておくとよいでしょう。
<js-module src="www/checkIsDebugPlugin.js" name="pluginBridging"> <clobbers target="checkIsDebug" /> </js-module>
<js-module>
ディレクティブでは、Plugin内で外部から参照させるためのjsファイルを指定できます。
今回のPluginではCordovaプロジェクト本体とネイティブコードの橋渡しとして、www/
ディレクトリ内にcheckIsDebugPlugin.js
を追加していますので、これをsrc
属性に指定します。
name
属性は開発者が参照することはないので、任意の名前をつければOKです。
重要なのは内部のcolobbers
要素で、ここのtarget
属性で指定した値を使ってCordovaプロジェクトから関数として呼び出すことになります。
<platform name="android"> <config-file target="res/xml/config.xml" parent="/*"> <feature name="CheckIsDebug"> <param name="android-package" value="com.rs.tukki.testapp.plugin.checkisdebug.CheckIsDebugPlugin"/> </feature> </config-file> <source-file src="src/android/CheckIsDebugPlugin.java" target-dir="com/rs/tukki/testapp/plugin/checkisdebug/" /> </platform>
<platform>
では、各プラットフォームごとにどのような設定やネイティブコードが必要かを定義しています。
今回はAndroidに絞って解説します。
最初の<config-file>
ディレクティブでは、「このプラグインはこのような形でこのクラスを呼び出します」という情報をconfig.xml
に追記するための設定を行なっています。
<feature>
要素のname
属性が特に重要で、この値はcordova.exec
というネイティブコードを呼び出すための関数で第三引数に指定する必要があります。(後述)
<param>
要素のvalue
属性には呼び出す対象となるクラスをパッケージ名を含めて記載してください。
<source-file>
要素には、Android向けにプロジェクトを構築する際、ネイティブコードをプロジェクトに含めるために追加する必要がある項目です。
この記載がないとプロジェクト内にネイティブコードが含まれず、当然呼び出しに失敗します。
src
属性はこのplugin.xml
からの相対パスでjavaファイルを指定します。
target-dir
属性は構築されたプロジェクトでのファイルの配置先の指定に使います。
ここまで記載できればネイティブコードを呼び出す最低限のPlugin.xmlとしてはOKです。
(実際はネイティブコードを一切呼び出さないCordovaプラグインもあったりしますが...それはまた次の機会に)
続いてpackage.jsonを作成します。
ここでは依存性の注入や最初に呼ばれるスクリプトの設定などが行えます...が、
プラグインをOSSとして公開する必要がなく、最低限の実装だけ行いたい場合は必須の2項目だけ記載しておけばよいでしょう。
{ "version": "1.0.0", "name": "cordova-plugin-check-is-debug" }
そのほかの設定項目は以下を参考にしてみてください。
ネイティブコードの実装(CheckIsDebugPlugin.java)
さて、次はプラグインの本体となるJavaクラスを実装していきます。
JavaでCordovaプラグインを実装する場合、CordovaPlugin
クラスを継承したクラスを作成し、
executeメソッドをOverrideして処理を記載していきます。
今回はdebugビルドかどうかを取得したいので、javaコード上で判定処理を組み込み、返却用のJSONオブジェクトに格納します。
package com.rs.tukki.testapp.plugin.checkisdebug; import org.apache.cordova.CordovaPlugin; import org.apache.cordova.CallbackContext; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import io.cordova.hellocordova.BuildConfig; public class CheckIsDebugPlugin extends CordovaPlugin { @Override public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { JSONObject result = new JSONObject(); if (BuildConfig.DEBUG) { result.put("isDebug", true); } else { result.put("isDebug", false); } callbackContext.success(result); return true; } }
最終的に、executeはbool値を戻り値として返します。
trueなら成功時のcallbackが、falseなら失敗時のcallbackが呼ばれます。
この前に、callbackContextのsuccessメソッドもしくはerrorメソッドにパラメータを格納しておけば、callback内でその値を参照することができます。
ネイティブコードを呼び出す(checkIsDebugPlugin.js)
さて、次はこのネイティブコードをフロント側から呼び出せるようにします。
ネイティブコードは直接Cordovaプロジェクト側から呼び出す方法もなくはないですが、基本的には一旦プラグイン内のjsコードを挟むことになります。
const CheckIsDebugPlugin = function () { }; CheckIsDebugPlugin.prototype.isDebug = function (success, fail) { cordova.exec(success, fail, "CheckIsDebug", "isDebug", []); }; const checkIsDebug = new CheckIsDebugPlugin(); module.exports = checkIsDebug;
cordova.exec
はネイティブコードを呼び出すためのメソッドです。
第一引数と第二引数はそれぞれ成功時、失敗時のコールバック、
第三引数はplugin.xml
のfeature
要素で指定した値、
第四引数はネイティブコード内で処理を判別するための文字列、
第五引数は任意のパラメータを取ります。
この関数をexportsすることで、Plugin.xml
のclobbers
要素で指定したtarget名で呼び出すことができます。
すなわち、実際に呼び出す際は以下のような形になります。
成功した場合のコールバック処理でははdebugビルドかどうかを表示するようにしておきましょう。
window.checkIsDebug.isDebug(result => { console.log(result.isDebug); document.getElementById("isDebug").textContent = "debugMode is " + result.isDebug; }, err => { console.log(err); document.getElementById("isDebug").textContent = "error!:" + err; });
動作確認
さて、これでPluginを導入したCordovaアプリのサンプルが作成できましたので、
早速実機で動作確認をしてみましょう。
アプリの動作確認は、以下の順序で行います。
なお、Androidでビルドを行う場合はSDKにパスを通す必要があるので忘れずに行っておきましょう。
cordova plugin add [フォルダパス]
で作成したCordova Pluginを登録するcordova platform add [プラットフォーム名]
で各プラットフォーム向けにビルドの準備をするcordova run [プラットフォーム名]
でアプリをビルドし、実行する
release向けにビルドを行う場合はもう少し詳細に設定が必要ですが、debug版での動作確認はひとまずこれだけできれば十分です。
$ cordova plugin add plugin/cordova-plugin-check-is-debug Installing "cordova-plugin-check-is-debug" for android Adding cordova-plugin-check-is-debug to package.json $ cordova platform add android Using cordova-fetch for cordova-android@^9.0.0 Adding android project... Creating Cordova project for the Android platform: Path: platforms/android Package: io.cordova.hellocordova Name: HelloCordova Activity: MainActivity Android target: android-29 Subproject Path: CordovaLib Subproject Path: app Android project created with cordova-android@9.1.0 Discovered plugin "cordova-plugin-whitelist". Adding it to the project Installing "cordova-plugin-whitelist" for android Adding cordova-plugin-whitelist to package.json $ cordova run android Checking Java JDK and Android SDK versions ANDROID_SDK_ROOT=/Users/your_name/Library/Android/SDK (recommended setting) ANDROID_HOME=/Users/your_name/Library/Android/SDK (DEPRECATED) Using Android SDK: /Users/your_name/Library/Android/SDK Starting a Gradle Daemon (subsequent builds will be faster) Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0. You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins. See https://docs.gradle.org/7.3/userguide/command_line_interface.html#sec:command_line_warnings BUILD SUCCESSFUL in 7s 1 actionable task: 1 executed Subproject Path: CordovaLib Subproject Path: app Downloading https://services.gradle.org/distributions/gradle-6.5-all.zip .............10%..............20%..............30%..............40%..............50%..............60%..............70%..............80%..............90%..............100% Starting a Gradle Daemon (subsequent builds will be faster) Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0. Use '--warning-mode all' to show the individual deprecation warnings. See https://docs.gradle.org/6.5/userguide/command_line_interface.html#sec:command_line_warnings BUILD SUCCESSFUL in 1m 57s 40 actionable tasks: 40 executed Built the following apk(s): /Users/your_name/workspace/testApp/platforms/android/app/build/outputs/apk/debug/app-debug.apk Checking Java JDK and Android SDK versions ANDROID_SDK_ROOT=/Users/your_name/Library/Android/SDK (recommended setting) ANDROID_HOME=/Users/your_name/Library/Android/SDK (DEPRECATED) Using Android SDK: /Users/your_name/Library/Android/SDK Deploying to device 0B161FDD4001VQ Using apk: /Users/your_name/workspace/testApp/platforms/android/app/build/outputs/apk/debug/app-debug.apk Package name: io.cordova.hellocordova INSTALL SUCCESS LAUNCH SUCCESS
コマンドを実行してアプリを起動すると、
デフォルトのTOPページに新しく追加したDEBUGMODE IS TRUE
の文字が確認できるかと思います。
おわりに
今回は、Cordovaプロジェクトの新規作成から、Android向けのCordovaプラグインを作成して動作確認するところまでを実装してみました。(iOSはまた機会があれば……)
仕組みさえ理解してしまえばKotlinやSwiftのネイティブアプリと遜色ないアプリを作れますし、なによりフロントエンドの知識で画面制御を実現できるのが圧倒的に便利ですので、まず何かアプリを作ってみたい!という方はCordovaを試してみてはいかがでしょうか。
参考
Cordovaを使って、Androidの実機実行するまで - Qiita
MacでCordovaのインストール・実行・ビルドまで (iOS, Android, Web) | 株式会社TKS2
Cordova PluginのJavaScript部分の実装 - Qiita
BuildConfig クラスでアプリの動作を切り替える | まくまくAndroidノート
Cordovaプラグインを開発してみよう! – モナカプレス
エンジニア中途採用サイト
ラクスでは、エンジニア・デザイナーの中途採用を積極的に行っております!
ご興味ありましたら是非ご確認をお願いします。
https://career-recruit.rakus.co.jp/career_engineer/カジュアル面談お申込みフォーム
どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。
以下フォームよりお申込みください。
rakus.hubspotpagebuilder.comラクスDevelopers登録フォーム
https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/イベント情報
会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください!
◆TECH PLAY
techplay.jp
◆connpass
rakus.connpass.com