- Add withOppoPush.js and withVivoPush.js config plugins - Register new plugins in app.json - Bump JPush version from 5.8.0 to 6.1.0 in Honor/Huawei/Xiaomi plugins
206 lines
7.3 KiB
JavaScript
206 lines
7.3 KiB
JavaScript
const {
|
||
withProjectBuildGradle,
|
||
withSettingsGradle,
|
||
withDangerousMod,
|
||
} = require('@expo/config-plugins');
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
|
||
// 荣耀厂商推送通道的 Expo config plugin.
|
||
//
|
||
// 客户端职责(依据极光官方文档 https://docs.jiguang.cn/jpush/client/Android/android_3rd_guide):
|
||
// 1) 添加 cn.jiguang.sdk.plugin:honor 依赖
|
||
// 2) 注入 manifestPlaceholders: HONOR_APPID
|
||
// 3) 添加荣耀 Maven 仓库 https://developer.hihonor.com/repo (v5.9.0+ 必需)
|
||
// 4) 添加 Proguard 规则 (com.hihonor.push.** 保留 + 5 条 -keepattributes)
|
||
//
|
||
// 实现说明:app/build.gradle 改动用 withDangerousMod 直接读写磁盘文件。
|
||
// 原因:Expo SDK 56+ 的 withAppBuildGradle hook 链中,第二个以后的 plugin 写回
|
||
// modResults.contents 会被静默忽略,导致多个 vendor plugin 只能写入第一个的修改。
|
||
// 仓库(settings.gradle / build.gradle)改动用 withProjectBuildGradle / withSettingsGradle
|
||
// 没有这个问题。
|
||
const withHonorPush = (config, options = {}) => {
|
||
const {
|
||
jpushVersion = '6.1.0',
|
||
appId = '104562917',
|
||
} = options;
|
||
|
||
const honorRepoUrl = 'https://developer.hihonor.com/repo';
|
||
|
||
// 1. settings.gradle: 添加荣耀 Maven 仓库
|
||
config = withSettingsGradle(config, (config) => {
|
||
let contents = config.modResults.contents;
|
||
|
||
if (!contents.includes('developer.hihonor.com/repo')) {
|
||
const repoLine = ` maven { url '${honorRepoUrl}' }`;
|
||
const hasRepositoriesInPM = /pluginManagement\s*\{[\s\S]*?repositories\s*\{/.test(contents);
|
||
|
||
if (hasRepositoriesInPM) {
|
||
config.modResults.contents = contents.replace(
|
||
/(pluginManagement\s*\{[\s\S]*?repositories\s*\{)/,
|
||
`$1\n ${repoLine}`
|
||
);
|
||
} else if (contents.includes('pluginManagement')) {
|
||
config.modResults.contents = contents.replace(
|
||
/(pluginManagement\s*\{)/,
|
||
`$1\n repositories {\n gradlePluginPortal()\n google()\n mavenCentral()\n ${repoLine}\n }`
|
||
);
|
||
} else {
|
||
config.modResults.contents =
|
||
`pluginManagement {\n repositories {\n ${repoLine}\n }\n}\n\n` +
|
||
config.modResults.contents;
|
||
}
|
||
}
|
||
|
||
// Gradle 9+ layout
|
||
if (
|
||
!config.modResults.contents.match(
|
||
/dependencyResolutionManagement[\s\S]*developer\.hihonor\.com\/repo/
|
||
)
|
||
) {
|
||
const depMgmtPattern = /dependencyResolutionManagement\s*\{[\s\S]*?repositories\s*\{/;
|
||
if (depMgmtPattern.test(config.modResults.contents)) {
|
||
config.modResults.contents = config.modResults.contents.replace(
|
||
depMgmtPattern,
|
||
`$&\n maven { url '${honorRepoUrl}' }`
|
||
);
|
||
}
|
||
}
|
||
|
||
return config;
|
||
});
|
||
|
||
// 2. 根 build.gradle: 添加荣耀 Maven 仓库到 buildscript.repositories
|
||
config = withProjectBuildGradle(config, (config) => {
|
||
let contents = config.modResults.contents;
|
||
|
||
if (!contents.includes('developer.hihonor.com/repo')) {
|
||
const bsRepoPattern = /(buildscript\s*\{[\s\S]*?repositories\s*\{)/;
|
||
if (bsRepoPattern.test(contents)) {
|
||
contents = contents.replace(
|
||
bsRepoPattern,
|
||
`$1\n maven { url '${honorRepoUrl}' }`
|
||
);
|
||
}
|
||
}
|
||
|
||
config.modResults.contents = contents;
|
||
return config;
|
||
});
|
||
|
||
// 3. app/build.gradle: 注入 AAR 依赖 + manifestPlaceholders (用 withDangerousMod 直接读文件)
|
||
config = withDangerousMod(config, [
|
||
'android',
|
||
async (config) => {
|
||
const appBuildGradlePath = path.join(
|
||
config.modRequest.platformProjectRoot,
|
||
'app',
|
||
'build.gradle'
|
||
);
|
||
const proguardFilePath = path.join(
|
||
config.modRequest.platformProjectRoot,
|
||
'app',
|
||
'proguard-rules.pro'
|
||
);
|
||
|
||
// --- 3a. 处理 build.gradle ---
|
||
if (fs.existsSync(appBuildGradlePath)) {
|
||
let gradle = fs.readFileSync(appBuildGradlePath, 'utf-8');
|
||
let changed = false;
|
||
|
||
// 注入 cn.jiguang.sdk.plugin:honor 依赖
|
||
if (!gradle.includes('cn.jiguang.sdk.plugin:honor')) {
|
||
const depsPattern = /dependencies\s*\{/;
|
||
if (depsPattern.test(gradle)) {
|
||
gradle = gradle.replace(
|
||
depsPattern,
|
||
`dependencies {\n implementation 'cn.jiguang.sdk.plugin:honor:${jpushVersion}'`
|
||
);
|
||
changed = true;
|
||
}
|
||
}
|
||
|
||
// 注入 manifestPlaceholders: HONOR_APPID
|
||
const manifestPlaceholderRegex = /manifestPlaceholders\s*=\s*\[([\s\S]*?)\]/;
|
||
const match = gradle.match(manifestPlaceholderRegex);
|
||
|
||
const requiredPlaceholders = {
|
||
HONOR_APPID: appId,
|
||
};
|
||
|
||
if (match) {
|
||
const existingBlock = match[1];
|
||
const existingEntries = {};
|
||
const entryRegex = /(\w+)\s*:\s*"([^"]*)"/g;
|
||
let entryMatch;
|
||
while ((entryMatch = entryRegex.exec(existingBlock)) !== null) {
|
||
existingEntries[entryMatch[1]] = entryMatch[2];
|
||
}
|
||
|
||
let placeholdersChanged = false;
|
||
for (const [key, value] of Object.entries(requiredPlaceholders)) {
|
||
if (existingEntries[key] !== value) {
|
||
existingEntries[key] = value;
|
||
placeholdersChanged = true;
|
||
}
|
||
}
|
||
|
||
if (placeholdersChanged) {
|
||
const entriesStr = Object.entries(existingEntries)
|
||
.map(([k, v]) => `${k}: "${v}"`)
|
||
.join(',\n ');
|
||
const newBlock = `\n manifestPlaceholders = [\n ${entriesStr}\n ]`;
|
||
gradle = gradle.replace(manifestPlaceholderRegex, newBlock.trim());
|
||
changed = true;
|
||
}
|
||
} else if (gradle.includes('REACT_NATIVE_RELEASE_LEVEL')) {
|
||
// 没有 manifestPlaceholders block 时新建
|
||
const entriesStr = Object.entries(requiredPlaceholders)
|
||
.map(([k, v]) => `${k}: "${v}"`)
|
||
.join(',\n ');
|
||
const block = `\n manifestPlaceholders = [\n ${entriesStr}\n ]\n`;
|
||
const lines = gradle.split('\n');
|
||
for (let i = 0; i < lines.length; i++) {
|
||
if (lines[i].includes('REACT_NATIVE_RELEASE_LEVEL')) {
|
||
lines.splice(i + 1, 0, block);
|
||
break;
|
||
}
|
||
}
|
||
gradle = lines.join('\n');
|
||
changed = true;
|
||
}
|
||
|
||
if (changed) {
|
||
fs.writeFileSync(appBuildGradlePath, gradle);
|
||
console.log('[withHonorPush] updated app/build.gradle (AAR + manifestPlaceholders)');
|
||
}
|
||
}
|
||
|
||
// --- 3b. 处理 proguard-rules.pro ---
|
||
if (fs.existsSync(proguardFilePath)) {
|
||
let proguard = fs.readFileSync(proguardFilePath, 'utf-8');
|
||
if (!proguard.includes('-keep class com.hihonor.push.**')) {
|
||
const honorRules = `
|
||
# JPush Honor vendor channel — keep rules (https://docs.jiguang.cn/jpush/client/Android/android_3rd_guide)
|
||
-ignorewarnings
|
||
-keepattributes *Annotation*
|
||
-keepattributes Exceptions
|
||
-keepattributes InnerClasses
|
||
-keepattributes Signature
|
||
-keepattributes SourceFile,LineNumberTable
|
||
-keep class com.hihonor.push.**{*;}
|
||
`;
|
||
fs.writeFileSync(proguardFilePath, proguard + honorRules);
|
||
console.log('[withHonorPush] appended Honor Proguard rules to proguard-rules.pro');
|
||
}
|
||
}
|
||
|
||
return config;
|
||
},
|
||
]);
|
||
|
||
return config;
|
||
};
|
||
|
||
module.exports = withHonorPush;
|