自定义 Maps Config Plugin 实战

Created on

前言

在真实项目里,地图接入经常遇到两个问题:不同地区的地图服务差异,以及多环境 Key 与原生配置的复杂性。用 Config Plugin 把这些配置固化下来,才能保证 prebuild 和升级的稳定性。

本文以“高德 + Google Maps 双栈”作为目标,拆解一个可复用的地图插件设计与落地方式。

设计目标

插件入口:统一解析与分发

一个合理的入口应负责三件事:

  1. 解析环境变量占位符
  2. 生成高德与 Google 的配置
  3. 按需组合多个子插件

示例结构:

const { withPlugins } = require("@expo/config-plugins");
const withGoogleMapsAndroid = require("./withGoogleMapsAndroid");
const withGoogleMapsIOS = require("./withGoogleMapsIOS");
const withGaodeMap = require("expo-gaode-map/app.plugin");

const withMaps = (config, props = {}) => {
  const iosKey = resolveEnvPlaceholder(
    props.iosKey || process.env.EXPO_PUBLIC_GAODE_IOS_API_KEY || ""
  );
  const androidKey = resolveEnvPlaceholder(
    props.androidKey || process.env.EXPO_PUBLIC_GAODE_ANDROID_API_KEY || ""
  );
  const googleMapsApiKey = resolveEnvPlaceholder(
    props.googleMapsApiKey || process.env.EXPO_PUBLIC_GOOGLE_MAPS_KEY || ""
  );

  const plugins = [];
  if (iosKey || androidKey) {
    plugins.push([withGaodeMap, { iosKey, androidKey }]);
  }
  if (googleMapsApiKey) {
    plugins.push([withGoogleMapsAndroid, { googleMapsApiKey }]);
    plugins.push([withGoogleMapsIOS, { googleMapsApiKey }]);
  }

  return withPlugins(config, plugins);
};

Android: Manifest + Gradle

Google Maps 的 Android 侧需要两块配置:

  1. Manifest meta-data 写入 API Key
  2. app/build.gradle 添加 Google Play Services 依赖

示例片段:

AndroidConfig.Manifest.addMetaDataItemToMainApplication(
  mainApplication,
  "com.google.android.geo.API_KEY",
  props.googleMapsApiKey,
  "value"
);

// build.gradle
implementation "com.google.android.gms:play-services-maps:18.2.0"
implementation "com.google.android.gms:play-services-location:21.0.1"

同时建议补齐定位权限,避免地图加载但无法获取位置信息。

iOS: Info.plist 注入

Google Maps 的 iOS 侧只需要写入 GMSApiKey,并确保定位文案存在:

config.modResults.GMSApiKey = props.googleMapsApiKey;
config.modResults.NSLocationWhenInUseUsageDescription ||=
  "我们需要访问您的位置以显示您附近的服务";

高德: 使用官方插件

高德 SDK 的原生接入较复杂,推荐直接调用 expo-gaode-map 官方插件。你的自定义插件只需要做两件事:

这样既复用社区维护能力,又避免自己维护原生 SDK 更新。

运行时切换地图提供商

在 JS 层通过环境变量决定使用哪个 Provider:

const provider = process.env.EXPO_PUBLIC_MAP_PROVIDER;
// gaode 或 google

这样可以实现:

在 app.config 中启用

[
  "@repo/maps/plugin",
  {
    iosKey: process.env.EXPO_PUBLIC_GAODE_IOS_API_KEY,
    androidKey: process.env.EXPO_PUBLIC_GAODE_ANDROID_API_KEY,
    googleMapsApiKey: process.env.EXPO_PUBLIC_GOOGLE_MAPS_KEY,
    enableLocation: true,
    enableBackgroundLocation: false,
  },
];

验证流程

  1. expo prebuild 后检查 AndroidManifest 与 Info.plist
  2. 真机运行确认定位权限与地图加载
  3. 切换地图提供商验证渲染差异

小结

一个好的 Maps Config Plugin 不只是“写 Key”,而是把多地图服务、多环境 Key、原生配置差异封装成统一入口。只要这层稳定,地图能力在项目内的复用成本会大幅下降。