Cordovaでは、CordovaコマンドをカスタマイズできるようにHook スクリプトという仕組みを用意しています。Hook スクリプトにつきましては、以下を参照していください。
Hook スクリプトは、ビルド時のプラットフォームを追加する前や後、Cordovaプラグインを追加する前や後等、Cordovaコマンドが実行されるタイミングで処理を行う事ができます。そのため、Hook スクリプトは、Cordovaプラグイン専用の仕組みではありませんが、Cordovaプラグインでも利用できるため、今回は、Hook スクリプトについて説明していきたいと思います。
古い記事になりますが、 Hook スクリプトについては、以下も参考にしてください。
Hook スクリプトの利用方法
Hook スクリプトは、以下のファイルから利用する事ができます。
- config.xml
- plugin.xml
Hook スクリプトを利用する場合は、以下のように、config.xmlやplugin.xml内で <hook> 要素を追加する形で利用します。
<hook type="before_build" src="scripts/appBeforeBuild.js" />
<hook> 要素
<hook> 要素のtype属性では、Hook スクリプトを実行するHook タイプを指定します。CordovaがサポートしているHook タイプについては、以下を参照してください。
src属性には、実行するHook スクリプトのファイルパスを指定します。
検証内容
Androidプラットフォーム 12系を使用して、AndroidのtargetSdkVersionを35に設定してビルドを実行した場合、以下のようなビルドエラーが発生します。Androidプラットフォーム 13系では、以下のようなビルドエラーは、発生しません。
Execution failed for task ':app:processDebugResources'.
> A failure occurred while executing com.android.build.gradle.internal.res.LinkApplicationAndroidResourcesTask$TaskAction
> Android resource linking failed
aapt2 E 06-10 16:38:32 955 955 LoadedArsc.cpp:94] RES_TABLE_TYPE_TYPE entry offsets overlap actual entry data.
aapt2 E 06-10 16:38:32 955 955 ApkAssets.cpp:149] Failed to load resources table in APK '/usr/local/android-sdk/platforms/android-35/android.jar'.
error: failed to load include path /usr/local/android-sdk/platforms/android-35/android.jar.
CordovaプラグインからHook スクリプトを利用する検証例として、これまでの説明で使用してきたサンプル用のCordovaプラグインを使用して、上記のビルドエラーを回避してみたいと思います。
検証用プロジェクトの設定
今回は、検証用プロジェクトとして、Monacaで提供している最小限のテンプレートから新規プロジェクトを作成して使用します。最小限のテンプレートは、Monaca Dashboardの新しいプロジェクトを作るから作成できます。

最小限のテンプレートから作成したプロジェクトをMonacaクラウドIDEで開き、以下のメニューを選択します。
- ビルド - ビルド環境の設定
ビルド環境の設定画面のANDROIDタブを選択し、以下の項目を選択して保存ボタンをクリックします。
- プラットフォーム:Android 12.0.1
- Javaバージョン:Java 11

次に、以下のメニューを選択します。
- 設定 - Androidアプリ設定
ターゲットSDKバージョン項目に35を設定して、保存ボタンをクリックします。

Androidアプリ設定画面のターゲットSDKバージョン項目の情報は、config.xmlの<android> 要素の配下に、以下の情報が設定されます。
<preference name="android-targetSdkVersion" value="35"/>
この状態で、Androidデバッグビルドを実行すると、上記のエラーが発生します。
Cordovaプラグインの設定
今回は、これまでの説明で使用してきたサンプル用のCordovaプラグインからHook スクリプトを実行してandroid-targetSdkVersion設定をAndroidプラットフォーム 12系のデフォルト値(33)に修正する形でビルドエラーを回避したいと思います。
上記のビルドエラーは、Androidプラットフォーム 12系で発生し、13系では発生しないため、検証目的として、CordovaプラグインがサポートするAndroidプラットフォームのバージョンは、13未満とします。
plugin.xmlの設定
Cordovaプラグインのplugin.xmlに、以下の<engines> 要素を追加します。以下の設定を追加することで、Androidプラットフォーム 13以上には、ビルド時にCordovaプラグインがインストールされなくなります。
<engines>
<engine name="cordova-android" version="<13.0.0" />
</engines>
config.xmlのandroid-targetSdkVersion設定を修正する場合、指定するHook タイプは、プラットフォームが追加される前のbefore_platform_addで行う方が良いと思いますが、今回は、CordovaプラグインからHook スクリプトを実行することが目的のため、Cordovaプラグインがインストールされる前のbefore_plugin_installで処理を行います。
plugin.xmlの<platform> 要素に、以下の<hook> 要素を追加します。
<platform name="android">
<hook type="before_plugin_install" src="scripts/before_plugin_install_android.js" />
<config-file parent="/*" target="res/xml/config.xml">
<feature name="SamplePlugin">
<param name="android-package" value="cordova.plugin.sample.SamplePlugin" />
</feature>
</config-file>
<config-file parent="/*" target="AndroidManifest.xml"></config-file>
<source-file src="src/android/SamplePlugin.java" target-dir="src/cordova.plugin.sample/SamplePlugin" />
</platform>
実行するHook スクリプトファイル(before_plugin_install_android.js)は、Cordovaプラグインの以下に保存します。
- ルート/scripts/before_plugin_install_android.js
before_plugin_install_android.jsの設定
ビルドサーバ環境では、Node.js上でHook スクリプトが実行されるため、Hook スクリプトを作成する場合は、以下のモジュールを定義し、必要な処理を記述していきます。
module.exports = function(context) {
...
}
functionに渡されるcontextオプジェクトの内容は、実行されるHook タイプによって内容が変化します。以下は、before_plugin_installで渡されるcontextオプジェクトの抜粋です。
{
"hook": "before_plugin_install",
"opts": {
"cordova": {
"platforms": [
"android"
],
"plugins": [
"cordova-plugin-sample"
],
"version": "12.0.1"
},
"plugin": {
"id": "cordova-plugin-sample",
"pluginInfo": {
"id": "cordova-plugin-sample",
"version": "1.0.0",
"name": "SamplePlugin"
},
"platform": "android"
},
"projectRoot": "projectRootパス"
},
"cmdLine": "cmdLineパス",
"scriptLocation": "projectRootパス/plugins/cordova-plugin-sample/scripts/before_plugin_install_android.js"
}
今回の処理では、config.xmlのファイルパスが必要になるため、上記のprojectRootの値を使用します。
Cordovaでは、cordova-commonというnpmパッケージを提供しており、cordova-commonでは、config.xmlを操作するConfigParserという機能を提供しています。今回は、config.xmlに設定されているandroid-targetSdkVersion設定を修正して保存するために、ConfigParserを使用します。
ConfigParserが提供している機能については、以下を参照してください。
before_plugin_install_android.jsの処理内容は、以下になります。
module.exports = function(context) {
const cordovaCommon = context.requireCordovaModule('cordova-common');
const configParser = cordovaCommon.ConfigParser;
const CONFIG_PATH = context.opts.projectRoot + "/config.xml"
const appConfig = new configParser(CONFIG_PATH);
var androidTargetSdkVersion = appConfig.getPlatformPreference("android-targetSdkVersion", "android");
if (androidTargetSdkVersion >= 35) {
appConfig.setPlatformPreference ("android-targetSdkVersion", "android", 33)
appConfig.write();
}
}
処理の内容については、以下になります。
- 2行目:contextオブジェクトからcordova-commonを取得し、cordovaCommon変数に代入しています。
- 3行目:cordovaCommonからConfigParserを取得し、configParser変数に代入しています。
- 5行目:context.opts.projectRootからプロジェクトのルートパスを取得してconfig.xmlのファイルパスを作成し、CONFIG_PATH変数に代入しています。
- 6行目:CONFIG_PATHを使用してconfigParserからConfigParserオブジェクト型のインスタンスを作成し、appConfig変数に代入しています。
- 8行目:ConfigParserのgetPlatformPreferenceメソッドを使用して、config.xmlに設定されているandroid-targetSdkVersionの値を取得し、androidTargetSdkVersion変数に代入しています。
- 9行目:androidTargetSdkVersion変数に代入された値をチェックし、35以上が設定されている場合は、後続の処理が実行されます。
- 10行目:ConfigParserのsetPlatformPreferenceメソッドを使用して、android-targetSdkVersionの値をAndroidプラットフォーム 12系のデフォルト値(33)をセットしています。
- 11行目:ConfigParserのwriteメソッドを使用して、変更後の情報をconfig.xmlに保存しています。
今回作成したCordovaプラグインを検証用プロジェクトにインポートしてAndroidデバッグビルドを実行すると、正常にビルドが完了します。
注意点として、ビルド時にHook スクリプトを使用してconfig.xmlを更新する場合、プロジェクトにHook スクリプトを使用してconfig.xmlを更新する他のCordovaプラグインがある場合、処理のタイミングによっては、正常に設定が反映されない場合があります。
Hook スクリプトの処理内容がconfig.xmlに反映されない場合は、Hook スクリプトを使用してconfig.xmlを更新する他のCordovaプラグインがないか確認してみてください。
おわりに
今回は、Hook スクリプトを使用してCordovaプラグインからconfig.xmlの設定を変更する例を紹介しました。今回は、Cordovaが提供している機能だけを利用してHook スクリプトを作成しましたが、以下のようなnpmパッケージを利用することで、Xcodeのxcodeprojファイルやplistファイルを操作することも可能です。
開発の難易度は高くなりますが、Hook スクリプトに興味があれば、一度、チャレンジしてみてください。