Skip to content

Commit 782655e

Browse files
author
Amigo-Bot
committed
docs: 修复 README 目录锚点链接,恢复完整文档内容
- 恢复被截断的文档章节(从 68 行恢复到 365 行) - 修正项目结构树,补充 utils/ 下的实际文件 - 新增 CHANGELOG.md 和 DEVELOPMENT.md 交叉引用 - 新增配置说明章节,区分 iOS/Android 配置项 - 优化文档导航,添加相关文档链接
1 parent 2916d0d commit 782655e

1 file changed

Lines changed: 304 additions & 9 deletions

File tree

README.md

Lines changed: 304 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,6 @@
2626
> - [Expo SDK 53+ 集成极光推送 iOS Swift](https://juejin.cn/post/7554288083597885467)
2727
> - [RunoMeow/jpush-expo-config-plugin](https://github.com/RunoMeow/jpush-expo-config-plugin)
2828
29-
## 最新特性
30-
31-
-**完整厂商通道支持**:覆盖华为、FCM、小米、OPPO、VIVO、魅族、荣耀、蔚来等主流厂商,自动配置SDK依赖与原生参数
32-
-**安全密钥管理**:Android 敏感参数支持从环境变量/gradle.properties读取,不再明文写入构建脚本
33-
-**iOS 安全优化**:JPush 初始化参数从 Info.plist 读取,不再直接注入 AppDelegate.swift 源码
34-
-**多环境适配**:支持生产/开发环境自动切换 APNs 配置,适配 CI/CD 流水线
35-
-**幂等注入机制**:Swift 桥接头文件、后台模式配置自动合并,不会覆盖宿主项目已有配置
36-
3729
## 目录
3830

3931
- [为什么使用它](#为什么使用它)
@@ -66,4 +58,307 @@
6658
- 你使用 Expo,但需要 JPush 和厂商通道能力
6759
- 你希望把原生改动交给 Config Plugin 管理,而不是手改生成代码
6860
- 你需要在 CI / 团队协作里稳定复现 `prebuild` 输出
69-
- 你需要严格的密钥安全管理,避免敏感信息泄露
61+
- 你需要严格的密钥安全管理,避免敏感信息泄露
62+
63+
## 支持矩阵
64+
65+
| 项目 | 版本 |
66+
| --- | --- |
67+
| Expo SDK | `53+` |
68+
| 仓库开发基线 | `Expo SDK 53` |
69+
| React Native | `0.76.9` |
70+
| Node.js | `>= 18.18.0` |
71+
| `jpush-react-native` | `3.1.9` |
72+
| `jcore-react-native` | `2.3.0` |
73+
74+
## 快速开始
75+
76+
### 1. 安装依赖
77+
78+
```bash
79+
npm install mx-jpush-expo
80+
npm install jpush-react-native@3.1.9 jcore-react-native@^2.3.0
81+
```
82+
83+
或使用 `pnpm`
84+
85+
```bash
86+
pnpm add mx-jpush-expo
87+
pnpm add jpush-react-native@3.1.9 jcore-react-native@^2.3.0
88+
```
89+
90+
### 2. 配置插件
91+
92+
推荐使用 `app.config.ts`,并把 Android 的敏感值交给环境变量或 `gradle.properties`
93+
94+
### 3. 生成原生工程
95+
96+
```bash
97+
npx expo prebuild
98+
```
99+
100+
只刷新 Android:
101+
102+
```bash
103+
npx expo prebuild -p android
104+
```
105+
106+
## 推荐配置
107+
108+
```ts
109+
import type { ConfigContext, ExpoConfig } from 'expo/config';
110+
import 'dotenv/config';
111+
112+
export default ({ config }: ConfigContext): ExpoConfig => {
113+
const isProduction = process.env.EXPO_PUBLIC_ENV === 'production';
114+
115+
return {
116+
...config,
117+
plugins: [
118+
...(config.plugins || []),
119+
[
120+
'mx-jpush-expo',
121+
{
122+
appKey: process.env.JPUSH_APP_KEY ?? '',
123+
channel: process.env.JPUSH_CHANNEL ?? 'developer-default',
124+
packageName:
125+
process.env.JPUSH_PKGNAME ?? config.android?.package ?? '',
126+
apsForProduction: isProduction,
127+
vendorChannels: {
128+
huawei: { enabled: true },
129+
fcm: { enabled: true },
130+
xiaomi: {
131+
appId: process.env.JPUSH_XIAOMI_APP_ID,
132+
appKey: process.env.JPUSH_XIAOMI_APP_KEY,
133+
},
134+
oppo: {
135+
appId: process.env.JPUSH_OPPO_APP_ID,
136+
appKey: process.env.JPUSH_OPPO_APP_KEY,
137+
appSecret: process.env.JPUSH_OPPO_APP_SECRET,
138+
},
139+
vivo: {
140+
appId: process.env.JPUSH_VIVO_APP_ID,
141+
appKey: process.env.JPUSH_VIVO_APP_KEY,
142+
},
143+
meizu: {
144+
appId: process.env.JPUSH_MEIZU_APP_ID,
145+
appKey: process.env.JPUSH_MEIZU_APP_KEY,
146+
},
147+
honor: {
148+
appId: process.env.JPUSH_HONOR_APP_ID,
149+
},
150+
nio: {
151+
appId: process.env.JPUSH_NIO_APP_ID,
152+
},
153+
},
154+
},
155+
],
156+
],
157+
};
158+
};
159+
```
160+
161+
### 配置要点
162+
163+
- `appKey``channel``packageName` 仍然是插件必填项
164+
- iOS 初始化参数会写入 `Info.plist`,不再直接拼进 `AppDelegate.swift`
165+
- Android `manifestPlaceholders` 优先读取环境变量或 `gradle.properties`
166+
- `vendorChannels` 决定要注入哪些厂商 SDK 与占位符,厂商密钥本身建议交给环境变量
167+
168+
## 环境变量与厂商通道
169+
170+
Android 端的 `manifestPlaceholders` 读取优先级如下:
171+
172+
1. `System.getenv("...")`
173+
2. `project.findProperty("...")`
174+
3. 插件收到的默认值,仅 `JPUSH_PKGNAME`
175+
4. 空字符串,其余字段
176+
177+
### 可用环境变量
178+
179+
| 变量名 | 说明 |
180+
| --- | --- |
181+
| `JPUSH_APP_KEY` | JPush AppKey |
182+
| `JPUSH_CHANNEL` | JPush Channel |
183+
| `JPUSH_PKGNAME` | Android 包名 |
184+
| `JPUSH_XIAOMI_APP_ID` / `JPUSH_XIAOMI_APP_KEY` | 小米通道 |
185+
| `JPUSH_OPPO_APP_ID` / `JPUSH_OPPO_APP_KEY` / `JPUSH_OPPO_APP_SECRET` | OPPO 通道 |
186+
| `JPUSH_VIVO_APP_ID` / `JPUSH_VIVO_APP_KEY` | VIVO 通道 |
187+
| `JPUSH_MEIZU_APP_ID` / `JPUSH_MEIZU_APP_KEY` | 魅族通道 |
188+
| `JPUSH_HONOR_APP_ID` | 荣耀通道 |
189+
| `JPUSH_NIO_APP_ID` | 蔚来通道 |
190+
191+
示例 `.env`
192+
193+
```bash
194+
JPUSH_APP_KEY=your-jpush-app-key
195+
JPUSH_CHANNEL=developer-default
196+
JPUSH_PKGNAME=com.your.app
197+
JPUSH_XIAOMI_APP_ID=your-xiaomi-app-id
198+
JPUSH_XIAOMI_APP_KEY=your-xiaomi-app-key
199+
```
200+
201+
### 厂商通道额外要求
202+
203+
| 厂商 | 额外文件 | 签名要求 | 说明 |
204+
| --- | --- | --- | --- |
205+
| 华为 | `agconnect-services.json` | 需要 | 需配置 SHA256 指纹 |
206+
| FCM | `google-services.json` | 不需要 | 需在 Firebase 控制台申请 |
207+
| 荣耀 || 需要 | 需配置 SHA256 指纹 |
208+
| 蔚来 || 需要 | 需配置应用签名 |
209+
| 小米 || 不需要 | 仅需 AppId / AppKey |
210+
| OPPO || 不需要 | 仅需 AppId / AppKey / AppSecret |
211+
| VIVO || 不需要 | 仅需 AppId / AppKey |
212+
| 魅族 || 不需要 | 仅需 AppId / AppKey |
213+
214+
官方参数说明见:[极光推送 Android 厂商通道参数获取](https://docs.jiguang.cn/jpush/client/Android/android_3rd_param)
215+
216+
## 配置说明
217+
218+
### iOS 配置
219+
220+
- `appKey`:JPush 后台创建应用后获得的 AppKey
221+
- `channel`:渠道标识,默认 `developer-default`
222+
- `apsForProduction`:是否使用生产环境 APNs,默认 `false`(开发环境)
223+
224+
### Android 配置
225+
226+
- `packageName`:Android 应用包名,用于 `manifestPlaceholders`
227+
- 厂商通道通过 `vendorChannels` 对象配置,每个厂商独立开关
228+
229+
## 插件会修改哪些原生文件
230+
231+
| 平台 | 文件 | 作用 |
232+
| --- | --- | --- |
233+
| iOS | `ios/<app>/Info.plist` | 写入 `JPUSH_*` 配置并合并 `UIBackgroundModes` |
234+
| iOS | `ios/<app>/AppDelegate.swift` | 注入 JPush 初始化、APNs 回调和代理扩展 |
235+
| iOS | `ios/<app>/<target>-Bridging-Header.h` | 复用或创建桥接头文件,保证 import 幂等 |
236+
| Android | `android/app/src/main/AndroidManifest.xml` | 写入 `JPUSH_APPKEY` / `JPUSH_CHANNEL` meta-data |
237+
| Android | `android/app/build.gradle` | 注入依赖、`manifestPlaceholders``abiFilters`、厂商插件 |
238+
| Android | `android/build.gradle` | 注入厂商 Maven 仓库与 classpath |
239+
| Android | `android/settings.gradle` | 注册 `jpush-react-native` / `jcore-react-native` 模块 |
240+
| Android | `android/gradle.properties` | 写入华为 AGC 兼容性开关 |
241+
242+
## 如何验证生成结果
243+
244+
重新执行 `expo prebuild` 后,建议检查:
245+
246+
### iOS
247+
248+
- `Info.plist` 中存在:
249+
- `JPUSH_APPKEY`
250+
- `JPUSH_CHANNEL`
251+
- `JPUSH_APS_FOR_PRODUCTION`
252+
- `UIBackgroundModes` 会保留宿主已有值,并补齐:
253+
- `fetch`
254+
- `remote-notification`
255+
- `AppDelegate.swift` 中存在 `JPUSHService.setup`
256+
- 如果项目使用 Swift,插件会优先复用已有 `SWIFT_OBJC_BRIDGING_HEADER`;未配置时会自动创建 `<target>-Bridging-Header.h`
257+
258+
### Android
259+
260+
`android/app/build.gradle` 中的 `manifestPlaceholders` 应保持"运行时读取",而不是写死明文:
261+
262+
```gradle
263+
manifestPlaceholders = [
264+
JPUSH_PKGNAME: System.getenv("JPUSH_PKGNAME") ?: (project.findProperty("JPUSH_PKGNAME") ?: "com.your.app"),
265+
JPUSH_APPKEY: System.getenv("JPUSH_APP_KEY") ?: (project.findProperty("JPUSH_APP_KEY") ?: ""),
266+
JPUSH_CHANNEL: System.getenv("JPUSH_CHANNEL") ?: (project.findProperty("JPUSH_CHANNEL") ?: "")
267+
]
268+
```
269+
270+
## 常见问题
271+
272+
### 是否支持 Expo Go?
273+
274+
不支持。JPush 需要原生工程和原生依赖,必须通过 `expo prebuild` 进入 Dev Client 或原生构建流程。
275+
276+
### 为什么 iOS 仍然要求在插件配置里填写 `appKey` / `channel`
277+
278+
因为参数校验和 `Info.plist` 注入都发生在 Expo 配置阶段。它们不会再被直接拼进 `AppDelegate.swift`,但仍然需要在配置阶段提供。
279+
280+
### Android 遇到 Gradle 插件版本错误怎么办?
281+
282+
如果你遇到类似 `com.android.tools.build:gradle is no set in the build.gradle file` 的错误,需要检查业务项目自己的 `android/build.gradle` 与 Expo 版本是否匹配。这不是本插件主动引入的行为变更。
283+
284+
### 直接改 `node_modules/mx-jpush-expo` 可以吗?
285+
286+
不建议。重装依赖后会丢失,正式方式建议使用 `pnpm patch mx-jpush-expo` 或维护自己的 fork。
287+
288+
## 开发与测试
289+
290+
```bash
291+
npm run build
292+
npm run test -- --runInBand
293+
npm run lint
294+
```
295+
296+
### 测试覆盖重点
297+
298+
- iOS `Info.plist` 合并与 Bridging Header 创建 / 幂等
299+
- iOS `AppDelegate.swift` 注入与幂等
300+
- Android `Manifest`、Gradle、Settings 和 `gradle.properties` 原生输出
301+
- fixture-based 回归测试,确保 `compileModsAsync` 输出稳定
302+
303+
更多开发细节见 [DEVELOPMENT.md](./DEVELOPMENT.md)
304+
305+
## 项目结构
306+
307+
```text
308+
mx-jpush-expo/
309+
├── app.plugin.js
310+
├── plugin/
311+
│ ├── src/
312+
│ │ ├── index.ts
313+
│ │ ├── types.ts
314+
│ │ ├── ios/
315+
│ │ │ ├── infoPlist.ts
316+
│ │ │ ├── appDelegate.ts
317+
│ │ │ └── bridgingHeader.ts
318+
│ │ ├── android/
319+
│ │ │ ├── androidManifest.ts
320+
│ │ │ ├── appBuildGradle.ts
321+
│ │ │ ├── projectBuildGradle.ts
322+
│ │ │ ├── settingsGradle.ts
323+
│ │ │ └── gradleProperties.ts
324+
│ │ └── utils/
325+
│ │ ├── codeValidator.ts
326+
│ │ ├── config.ts
327+
│ │ ├── generateCode.ts
328+
│ │ ├── sourceCode.ts
329+
│ │ └── vendorChannels.ts
330+
│ ├── __tests__/
331+
│ │ ├── fixtures/
332+
│ │ ├── iosFixture.ts
333+
│ │ ├── androidFixture.ts
334+
│ │ └── *.test.ts
335+
│ └── build/
336+
├── .github/workflows/ci.yml
337+
├── CHANGELOG.md
338+
├── DEVELOPMENT.md
339+
└── README.md
340+
```
341+
342+
插件内部说明见 [plugin/README.md](./plugin/README.md)
343+
344+
## 最近更新
345+
346+
完整更新历史请查看 [CHANGELOG.md](./CHANGELOG.md)
347+
348+
- iOS `UIBackgroundModes` 改为合并写入,不再覆盖宿主已有后台模式
349+
- Swift `Bridging Header` 支持优先复用、缺失自动创建,并保持幂等
350+
- 补齐 iOS / Android fixture-based 原生回归测试
351+
- 加入 ESLint 与 CI 质量闭环
352+
- 对齐 Expo SDK 53 的版本声明与仓库开发基线
353+
- Android 敏感参数支持环境变量 / `gradle.properties` 读取,不再明文写入构建脚本
354+
- iOS 初始化参数改为从 `Info.plist` 读取,不再直接注入 `AppDelegate.swift`
355+
356+
## 致谢与许可
357+
358+
感谢以下资料与实现思路的启发:
359+
360+
- [JPush 集成 Expo](https://juejin.cn/post/7423235127716659239)
361+
- [Expo SDK 53+ 集成极光推送 iOS Swift](https://juejin.cn/post/7554288083597885467)
362+
- [RunoMeow/jpush-expo-config-plugin](https://github.com/RunoMeow/jpush-expo-config-plugin)
363+
364+
本项目使用 [MIT License](./LICENSE)

0 commit comments

Comments
 (0)