Zenn
🕌

ReactNative + Expo + AppClip + NFC

2025/03/24に公開

react-native-app-clip + react-native-nfc-manager を組み合わせて使った場合、react-native-app-clipがAppClip側のentitlementsファイルを更新してくれないためAppClip側でNFCが有効にならない。

そのために以下のようにAppClipにもNFCの設定を行う。

scripts/add-nfc-entitlement-to-app-clip.js
/**
 * ExpoにはiOSのentitlementsを設定する機能があるが、
 * react-native-app-clipを使った場合AppClip側のentitlementsを設定できないので
 * 直接ファイルを修正して追加する
 *
 * iOS capabilities - Expo Documentation https://docs.expo.dev/build-reference/ios-capabilities/
 */

if (process.env.EAS_BUILD_PLATFORM !== "ios") {
  console.log("iOS ビルドではないため、スクリプトをスキップします。");
  process.exit(0);
}

const fs = require("fs");
const path = require("path");

// エンタイトルメントファイルのパス
const entitlementsPath = path.join(
  __dirname,
  "../ios/xxxClip/xxxClip.entitlements",
);

// ファイルが存在するか確認
if (!fs.existsSync(entitlementsPath)) {
  console.error(`エラー: ${entitlementsPath} が見つかりません。`);
  process.exit(1);
}

// ファイルの内容を読み込む
let content = fs.readFileSync(entitlementsPath, "utf8");

// すでに NFC エンタイトルメントが含まれているか確認
if (content.includes("com.apple.developer.nfc.readersession.formats")) {
  console.log("NFC エンタイトルメントはすでに追加されています。");
  process.exit(0);
}

// </dict> の前に NFC エンタイトルメントを追加
const nfcEntitlement = `    <key>com.apple.developer.nfc.readersession.formats</key>
    <array>
      <string>TAG</string>
    </array>`;

content = content.replace("  </dict>", `${nfcEntitlement}\n  </dict>`);

// 変更を保存
fs.writeFileSync(entitlementsPath, content, "utf8");

console.log("NFC エンタイトルメントが正常に追加されました。");

上記jsを eas-build-post-install 経由で実行する。

package.json
{
  "scripts": {
    "eas-build-post-install": "node ./scripts/add-nfc-entitlement-to-app-clip.js"
  },
  "dependencies": {
    "react-native-app-clip": "~0.5.1"
    "react-native-nfc-manager": "~3.16.1"
  }
}

ちなみにexpoは @expo/config-plugins というpackageを提供していて、その中には withEntitlementsPlist というfunctionも存在するが、 @expo/config-plugins の提供するfunctionはいずれもAppClipに対応していないため使用できない。

Discussion

ログインするとコメントできます