npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

mx-jpush-expo

v1.2.5

Published

Expo 集成极光推送(JPush)一体化解决方案,支持 iOS/Android 厂商通道

Readme

[!IMPORTANT] JPush 不支持 Expo Go。本项目面向 expo prebuild 后的原生工程,适用于 Dev Client 或原生构建流程。

[!TIP] 本项目持续参考并吸收以下资料:

目录

为什么使用它

mx-jpush-expo 把 Expo 项目接入 JPush 时最容易反复手改的原生步骤,收敛成一次 expo prebuild

  • 自动写入 iOS Info.plist 的 JPush 配置和后台模式
  • 自动注入 iOS AppDelegate.swift 的 JPush 初始化与回调代码
  • 自动复用或创建 Swift Bridging Header
  • 自动修改 Android AndroidManifest.xmlbuild.gradlesettings.gradle
  • 支持华为、FCM、小米、OPPO、VIVO、魅族、荣耀、蔚来等厂商通道注入
  • 敏感参数支持环境变量注入,避免密钥明文提交到代码仓库

适合这些场景:

  • 你使用 Expo,但需要 JPush 和厂商通道能力
  • 你希望把原生改动交给 Config Plugin 管理,而不是手改生成代码
  • 你需要在 CI / 团队协作里稳定复现 prebuild 输出
  • 你需要严格的密钥安全管理,避免敏感信息泄露

支持矩阵

| 项目 | 版本 | | --- | --- | | Expo SDK | 53+ | | 仓库开发基线 | Expo SDK 53 | | React Native | 0.76.9 | | Node.js | >= 18.18.0 | | jpush-react-native | 3.1.9 | | jcore-react-native | 2.3.0 |

快速开始

1. 安装依赖

npm install mx-jpush-expo
npm install [email protected] jcore-react-native@^2.3.0

或使用 pnpm

pnpm add mx-jpush-expo
pnpm add [email protected] jcore-react-native@^2.3.0

2. 配置插件

推荐使用 app.config.ts,并把 Android 的敏感值交给环境变量或 gradle.properties

3. 生成原生工程

npx expo prebuild

只刷新 Android:

npx expo prebuild -p android

如果你修改了 app.config.ts / app.json 中的插件参数,需要重新执行一次 prebuild,让最新配置重新落到原生工程。已经生成过原生目录时,建议按平台增量刷新;如果怀疑宿主工程里有历史残留,再使用 --clean 重新生成。

npx expo prebuild -p android --clean
npx expo prebuild -p ios --clean

推荐配置

import type { ConfigContext, ExpoConfig } from 'expo/config';
import 'dotenv/config';

export default ({ config }: ConfigContext): ExpoConfig => {
  const isProduction = process.env.EXPO_PUBLIC_ENV === 'production';

  return {
    ...config,
    plugins: [
      ...(config.plugins || []),
      [
        'mx-jpush-expo',
        {
          appKey: process.env.JPUSH_APP_KEY ?? '',
          channel: process.env.JPUSH_CHANNEL ?? 'developer-default',
          packageName:
            process.env.JPUSH_PKGNAME ?? config.android?.package ?? '',
          apsForProduction: isProduction,
          vendorChannels: {
            huawei: { enabled: true },
            fcm: { enabled: true },
            xiaomi: {
              appId: process.env.JPUSH_XIAOMI_APP_ID,
              appKey: process.env.JPUSH_XIAOMI_APP_KEY,
            },
            oppo: {
              appId: process.env.JPUSH_OPPO_APP_ID,
              appKey: process.env.JPUSH_OPPO_APP_KEY,
              appSecret: process.env.JPUSH_OPPO_APP_SECRET,
            },
            vivo: {
              appId: process.env.JPUSH_VIVO_APP_ID,
              appKey: process.env.JPUSH_VIVO_APP_KEY,
            },
            meizu: {
              appId: process.env.JPUSH_MEIZU_APP_ID,
              appKey: process.env.JPUSH_MEIZU_APP_KEY,
            },
            honor: {
              appId: process.env.JPUSH_HONOR_APP_ID,
            },
            nio: {
              appId: process.env.JPUSH_NIO_APP_ID,
            },
          },
        },
      ],
    ],
  };
};

配置要点

  • appKeychannelpackageName 仍然是插件必填项
  • iOS 初始化参数会写入 Info.plist,不再直接拼进 AppDelegate.swift
  • Android manifestPlaceholders 优先读取环境变量或 gradle.properties,缺失时会回退到插件配置里的 appKey / channel / packageName
  • 如果宿主已经定义了 manifestPlaceholders,插件会通过 manifestPlaceholders += [...] 追加 JPush 字段 非 JPush 的宿主键会被保留;如果宿主和插件都声明了同名的 JPUSH_* 键,后追加的 JPush 默认值会生效
  • Android app/build.gradle 注入不再依赖 versionName 所在行;缺少 versionName 或使用 Gradle 变量时也能稳定 prebuild
  • vendorChannels 决定要注入哪些厂商 SDK 与占位符;若声明某个厂商通道,就必须提供该厂商要求的必填字段
  • 厂商密钥仍然建议交给环境变量,避免把敏感信息直接提交到仓库

环境变量与厂商通道

Android 端的 manifestPlaceholders 读取优先级如下:

  1. System.getenv("...")
  2. project.findProperty("...")
  3. 插件收到的配置值:JPUSH_PKGNAMEJPUSH_APPKEYJPUSH_CHANNEL
  4. 空字符串,其余未提供默认值的字段

可用环境变量

| 变量名 | 说明 | | --- | --- | | JPUSH_APP_KEY | JPush AppKey | | JPUSH_CHANNEL | JPush Channel | | JPUSH_PKGNAME | Android 包名 | | JPUSH_XIAOMI_APP_ID / JPUSH_XIAOMI_APP_KEY | 小米通道 | | JPUSH_OPPO_APP_ID / JPUSH_OPPO_APP_KEY / JPUSH_OPPO_APP_SECRET | OPPO 通道 | | JPUSH_VIVO_APP_ID / JPUSH_VIVO_APP_KEY | VIVO 通道 | | JPUSH_MEIZU_APP_ID / JPUSH_MEIZU_APP_KEY | 魅族通道 | | JPUSH_HONOR_APP_ID | 荣耀通道 | | JPUSH_NIO_APP_ID | 蔚来通道 |

示例 .env

JPUSH_APP_KEY=your-jpush-app-key
JPUSH_CHANNEL=developer-default
JPUSH_PKGNAME=com.your.app
JPUSH_XIAOMI_APP_ID=your-xiaomi-app-id
JPUSH_XIAOMI_APP_KEY=your-xiaomi-app-key

厂商通道额外要求

| 厂商 | 额外文件 | 签名要求 | 说明 | | --- | --- | --- | --- | | 华为 | agconnect-services.json | 需要 | 需配置 SHA256 指纹 | | FCM | google-services.json | 不需要 | 需在 Firebase 控制台申请 | | 荣耀 | 无 | 需要 | 需配置 SHA256 指纹 | | 蔚来 | 无 | 需要 | 需配置应用签名 | | 小米 | 无 | 不需要 | 仅需 AppId / AppKey | | OPPO | 无 | 不需要 | 仅需 AppId / AppKey / AppSecret | | VIVO | 无 | 不需要 | 仅需 AppId / AppKey | | 魅族 | 无 | 不需要 | 仅需 AppId / AppKey |

官方参数说明见:极光推送 Android 厂商通道参数获取

配置说明

iOS 配置

  • appKey:JPush 后台创建应用后获得的 AppKey
  • channel:渠道标识,默认 developer-default
  • apsForProduction:是否使用生产环境 APNs,默认 false(开发环境)

Android 配置

  • packageName:Android 应用包名,用于 manifestPlaceholders
  • 厂商通道通过 vendorChannels 对象配置,每个厂商独立开关

插件会修改哪些原生文件

| 平台 | 文件 | 作用 | | --- | --- | --- | | iOS | ios/<app>/Info.plist | 写入 JPUSH_* 配置并合并 UIBackgroundModes | | iOS | ios/<app>/AppDelegate.swift | 注入 JPush 初始化、APNs 回调和代理扩展 | | iOS | ios/<app>/<target>-Bridging-Header.h | 复用或创建桥接头文件,保证 import 幂等 | | Android | android/app/src/main/AndroidManifest.xml | 写入 JPUSH_APPKEY / JPUSH_CHANNEL meta-data | | Android | android/app/build.gradle | 注入依赖、manifestPlaceholdersabiFilters、厂商插件 | | Android | android/build.gradle | 注入厂商 Maven 仓库与 classpath | | Android | android/settings.gradle | 注册 jpush-react-native / jcore-react-native 模块 | | Android | android/gradle.properties | 写入华为 AGC 兼容性开关 |

如何验证生成结果

重新执行 expo prebuild 后,建议检查:

iOS

  • Info.plist 中存在:
    • JPUSH_APPKEY
    • JPUSH_CHANNEL
    • JPUSH_APS_FOR_PRODUCTION
  • UIBackgroundModes 会保留宿主已有值,并补齐:
    • fetch
    • remote-notification
  • AppDelegate.swift 中存在 JPUSHService.setup
  • AppDelegate.swift 中的调试日志与 JPUSHService.setDebugMode() 会被 #if DEBUG 包裹,release 构建不再无条件打印
  • 如果项目使用 Swift,插件会优先复用已有 SWIFT_OBJC_BRIDGING_HEADER;未配置时会自动创建 <target>-Bridging-Header.h

Android

android/app/build.gradle 中的 JPush 占位符应保持"运行时读取",而不是写死明文:

manifestPlaceholders += [
    JPUSH_PKGNAME: System.getenv("JPUSH_PKGNAME") ?: (project.findProperty("JPUSH_PKGNAME") ?: "com.your.app"),
    JPUSH_APPKEY: System.getenv("JPUSH_APP_KEY") ?: (project.findProperty("JPUSH_APP_KEY") ?: "your-jpush-app-key"),
    JPUSH_CHANNEL: System.getenv("JPUSH_CHANNEL") ?: (project.findProperty("JPUSH_CHANNEL") ?: "developer-default")
]

也就是说:

  • 宿主原本的 manifestPlaceholders = [...] 配置会被保留
  • 对于宿主和插件都声明的 JPUSH_* 键,后追加的 JPush 值会在合并结果中生效
  • 对最终消费方,插件配置本身已经足够让 prebuild 产出可用的 Android 默认值
  • 对 CI / EAS / 多环境发布,依然推荐通过环境变量或 gradle.properties 在构建时覆盖这些值
  • 厂商通道密钥如果需要按环境切换,也应沿用同样的覆盖策略

常见问题

是否支持 Expo Go?

不支持。JPush 需要原生工程和原生依赖,必须通过 expo prebuild 进入 Dev Client 或原生构建流程。

为什么 iOS 仍然要求在插件配置里填写 appKey / channel

因为参数校验和 Info.plist 注入都发生在 Expo 配置阶段。它们不会再被直接拼进 AppDelegate.swift,但仍然需要在配置阶段提供。

Android 遇到 Gradle 插件版本错误怎么办?

如果你遇到类似 com.android.tools.build:gradle is no set in the build.gradle file 的错误,需要检查业务项目自己的 android/build.gradle 与 Expo 版本是否匹配。这不是本插件主动引入的行为变更。

直接改 node_modules/mx-jpush-expo 可以吗?

不建议。重装依赖后会丢失,正式方式建议使用 pnpm patch mx-jpush-expo 或维护自己的 fork。

插件发布后,消费方实际会拿到什么?

npm 包入口是根目录的 app.plugin.js,它会加载发布产物 plugin/build。这意味着:

  • 仓库开发者在发布新版本前,需要先执行 npm run build
  • package.jsonfiles 已包含 app.plugin.jsplugin/build,消费方不会直接运行 plugin/src 中的 TypeScript 源码
  • 如果你维护的是 fork 或 patch 包,发布前请先确认编译产物已同步更新,否则消费项目仍会执行旧逻辑

开发与测试

npm run build
npm run test -- --runInBand
npm run lint

测试覆盖重点

  • iOS Info.plist 合并与 Bridging Header 创建 / 幂等
  • iOS AppDelegate.swift 注入与幂等
  • Android Manifest、Gradle、Settings 和 gradle.properties 原生输出
  • fixture-based 回归测试,确保 compileModsAsync 输出稳定

更多开发细节见 DEVELOPMENT.md

项目结构

mx-jpush-expo/
├── app.plugin.js
├── plugin/
│   ├── src/
│   │   ├── index.ts
│   │   ├── types.ts
│   │   ├── ios/
│   │   │   ├── infoPlist.ts
│   │   │   ├── appDelegate.ts
│   │   │   └── bridgingHeader.ts
│   │   ├── android/
│   │   │   ├── androidManifest.ts
│   │   │   ├── appBuildGradle.ts
│   │   │   ├── projectBuildGradle.ts
│   │   │   ├── settingsGradle.ts
│   │   │   └── gradleProperties.ts
│   │   └── utils/
│   │       ├── codeValidator.ts
│   │       ├── generateCode.ts
│   │       └── sourceCode.ts
│   ├── __tests__/
│   │   ├── fixtures/
│   │   ├── iosFixture.ts
│   │   ├── androidFixture.ts
│   │   └── *.test.ts
│   └── build/
├── .github/workflows/ci.yml
├── CHANGELOG.md
├── DEVELOPMENT.md
└── README.md

插件内部说明见 plugin/README.md

最近更新

完整更新历史请查看 CHANGELOG.md

  • iOS UIBackgroundModes 改为合并写入,不再覆盖宿主已有后台模式
  • Swift Bridging Header 支持优先复用、缺失自动创建,并保持幂等
  • 补齐 iOS / Android fixture-based 原生回归测试
  • Android manifestPlaceholders 改为在宿主现有配置后追加,不再依赖 versionName 文本锚点
  • iOS AppDelegate.swift 中的 JPush 调试日志只在 DEBUG 构建启用
  • 加入 ESLint 与 CI 质量闭环
  • 对齐 Expo SDK 53 的版本声明与仓库开发基线
  • Android 敏感参数支持环境变量 / gradle.properties 读取,不再明文写入构建脚本
  • iOS 初始化参数改为从 Info.plist 读取,不再直接注入 AppDelegate.swift

致谢与许可

感谢以下资料与实现思路的启发:

本项目使用 MIT License