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 スクリプトに興味があれば、一度、チャレンジしてみてください。