-
Notifications
You must be signed in to change notification settings - Fork 5
Feat/update jpush #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
fix addCustomMessageListener 方法报错问题
更新Jpush4.8.1,新增对外API:设置用户属性。对外版本号293,
更新iOS Jpush4.8.1,新增对外API:设置用户属性。对外版本号294
解决iOS 杀死状态点击通知进入app没有回调通知的问题
【iOS】解决没有初始化,但是会请求通知权限弹窗的问题
升级iOS jpush SDK到4.9.0, 更新插件版本号为2.9.8
更新JPush 500
【iOS】更新到jpush5.0.0
更新JPush 500:适配新回调
更新demo的jcore版本,fixdemo警告
更新JPush 504,对外版本号2.9.9
更新版本号为3.1.2
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
WalkthroughThis PR upgrades the JPush React Native plugin with newer native SDKs (iOS 5.9.0, Android 34), adds support for in-app messaging, property management, and notification controls, modernizes the Gradle build system, updates Android manifest permissions and activities, and refreshes the example app infrastructure with Swift and contemporary tooling. Changes
Sequence DiagramsequenceDiagram
participant App as React App
participant JPushModule as JPush Module
participant Native as Native JPush SDK
participant Listener as Event Listener
rect rgb(200, 220, 255)
Note over App,Native: In-App Message Flow
Native->>JPushModule: onInAppMessageShow(message)
JPushModule->>JPushModule: convertInappMsg()
JPushModule->>Listener: emit(INAPP_MESSAGE_EVENT, {type: "show", ...})
Listener->>App: inappMessageListener(event)
App->>App: handleInAppMessage()
end
rect rgb(200, 220, 255)
Note over App,Native: Property Management Flow
App->>JPushModule: setProperties({property: value})
JPushModule->>Native: JPushInterface.setProperties()
JPushModule->>Listener: emit(TAG_ALIAS_EVENT, result)
Listener->>App: tagAliasListener(event)
end
rect rgb(220, 255, 220)
Note over App,Native: Notification Button Click Flow
Native->>JPushModule: onNotifyButtonClick(button)
JPushModule->>JPushModule: convertNotificationCustomButton()
JPushModule->>Listener: emit(NOTIFY_BUTTON_CLICK_EVENT, buttonData)
Listener->>App: notifyButtonClickListener(event)
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes This PR spans multiple systems (Android/iOS build systems, Java/Kotlin, Swift/Objective-C, XML resources, configuration files) with significant heterogeneity. While many changes follow repetitive patterns (adding constants, new methods, drawable files), the breadth requires understanding build configuration implications, manifest changes affecting app security/behavior, native method wiring across two platforms, and framework upgrades with API surface expansions. The iOS JPUSHService.h header alone introduces extensive nullability and API changes warranting careful review. Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 70
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (14)
ios/RCTJPushModule/jpush-ios-5.9.0.xcframework/ios-arm64/Headers/JPUSHService.h (1)
1-1011: Add missing delegate registration for in-app message handlers.The integration is mostly compatible with JPush SDK 5.9.0, but the newly implemented delegate methods won't be called without explicit registration.
Found: RCTJPushModule.m implements
JPUSHInAppMessageDelegate(lines 378–385), but never registers it via+setInAppMessageDelegate:.Required action: Add delegate registration, likely in
setupWithConfig:method:[JPUSHService setInAppMessageDelegate:self];Also check whether
JPUSHNotiInMessageDelegatemethods need similar setup. If those handlers are used, register that delegate too:[JPUSHService setNotiInMessageDelegate:self];Without explicit registration, the delegate callbacks won't fire even though the methods exist. Verify this is happening or add the registration calls.
android/src/main/java/cn/jiguang/plugins/push/helper/JPushHelper.java (1)
143-145: Improve error logging.Log the exception message to aid troubleshooting.
- }catch (Throwable throwable){ - JLogger.e(""); + } catch (Throwable throwable) { + JLogger.e("launchApp error: " + throwable.getMessage());index.d.ts (1)
41-46: I need to verify the exact type expectation on the native side. Let me check how theidis extracted from the ReadableMap.<!-- [scratchpad_update]
[observations]
From web search: ReadableMap can extract values with:
- getInt() for integers
- getDouble() for numbers/floats
- getString() for strings
- getBoolean() for booleans
The key finding: Numbers in JS are typically read as either getInt() or getDouble() in Java depending on context. Numbers are Java Number type that can be int, double, or Long.[pending]
- Still need to see the actual code in JPushModule.java:663-670 to determine which method is used to extract the notificationId
- Need to check JPushInterface.clearNotificationById signature
[scratchpad_end] -->Let me check the actual code in the native module to see how the ID is extracted:<!-- [scratchpad_update]
[key_finding]
From web search result 11-1 and 11-8: JPushInterface.clearNotificationById expects anintparameter:
"public static void clearNotificationById(Context context, int notificationId)"This definitively shows that the native Android API expects an
int, not aString.[updated_analysis]
- JPushInterface.clearNotificationById(Context context, int notificationId) - expects INT
- JavaScript passes number types which can be extracted as:
- readableMap.getInt() → extracts as integer
- readableMap.getDouble() → extracts as double
- Current TypeScript definition uses "String" (capital S - object wrapper), but should be "number" since:
- Native Android expects int
- JavaScript numbers are transmitted and should be typed as number in TypeScript
[conclusion]
The review comment is CORRECT:
- String should change to string (primitive vs object) ✓
- The type should actually be
number(not just string → string change)
- JPushInterface.clearNotificationById expects int
- Numbers in JS/TypeScript should be typed as "number"
[scratchpad_end] -->Perfect. The evidence is clear. JPushInterface.clearNotificationById expects an
intparameter:public static void clearNotificationById(Context context, int notificationId)The review comment is accurate. Let me verify there are no other issues and generate the rewritten response:
Change
notificationIdfromStringtonumberin the TypeScript type.The native Android API expects an int for the notificationId parameter, not a string. Update both occurrences (lines 45 and 209 in index.d.ts):
type NotificationId = { /** * 通知 ID * */ - notificationId: String; + notificationId: number; };And:
- static clearNotificationById(params: NotificationId):void; + static clearNotificationById(params: NotificationId): void;android/src/main/java/cn/jiguang/plugins/push/receiver/JPushModuleReceiver.java (2)
107-113: Possible NPE on message.extra.toString().extra may be null. Guard it to avoid crashes.
- writableMap.putString(JConstants.COMMAND_EXTRA, message.extra.toString()); + writableMap.putString( + JConstants.COMMAND_EXTRA, + message.extra == null ? null : message.extra.toString() + );
23-23: Avoid logging full payloads in production.toString() on messages may include PII. Gate logs behind a debug flag or redact extras.
Also applies to: 30-30, 46-46, 57-57, 68-68, 80-80, 87-87, 93-93, 99-99, 107-107, 118-118, 125-125, 132-132, 139-139
index.js (3)
9-9: Listener registry can leak and collide; removeListener only clears one subscription.Using a plain object keyed by function string risks collisions and supports only a single sub per callback. Store multiple subs per callback or return a subscription to remove. At minimum, delete the key after remove.
-const listeners = {} +const listeners = new Map()- static addConnectEventListener(callback) { - listeners[callback] = DeviceEventEmitter.addListener( - ConnectEvent, result => { - callback(result) - }) - } + static addConnectEventListener(callback) { + const sub = DeviceEventEmitter.addListener(ConnectEvent, callback) + const set = listeners.get(callback) ?? new Set() + set.add(sub) + listeners.set(callback, set) + return sub + }- static removeListener(callback) { - if (!listeners[callback]) { - return - } - listeners[callback].remove() - listeners[callback] = null - } + static removeListener(callback) { + const set = listeners.get(callback) + if (!set) return + for (const sub of set) sub.remove() + listeners.delete(callback) + }Apply the same “store sub then return it” pattern to other addXxxListener methods.
Also applies to: 609-616
38-43: Use strict equality.Prefer ===/!== over ==/!= to avoid coercion bugs.
Also applies to: 54-59, 75-81, 97-103, 117-123, 133-139, 153-159, 169-175, 191-196, 206-212, 222-228, 253-258, 265-271, 276-282, 295-300, 306-311, 316-321, 325-331, 351-357, 367-373, 378-384, 389-393, 398-402, 410-416, 421-427, 432-437, 439-444, 468-473, 494-498, 512-517, 537-542, 562-567, 671-675, 685-687, 701-705, 710-716, 717-723, 739-744, 746-751, 753-758, 760-765, 767-771, 773-779, 788-792
628-632: Android 13+ runtime permission.Consider exposing a helper to request POST_NOTIFICATIONS on API 33+. Current requestPermission text lists storage/location/phone; add notifications or document the requirement.
android/src/main/java/cn/jiguang/plugins/push/JPushModule.java (4)
45-48: Constructor passes wrong context to super.Use the incoming ReactApplicationContext.
- public JPushModule(ReactApplicationContext reactApplicationContext) { - super(reactContext); - reactContext = reactApplicationContext; - } + public JPushModule(ReactApplicationContext reactApplicationContext) { + super(reactApplicationContext); + reactContext = reactApplicationContext; + }
205-227: Allow 0:00 in setPushTime; use hasKey checks.The current 0 checks forbid midnight. Validate presence instead.
- ReadableArray readableArray = readableMap.getArray(JConstants.PUSH_TIME_DAYS); - int startHour = readableMap.getInt(JConstants.PUSH_TIME_START_HOUR); - int endHour = readableMap.getInt(JConstants.PUSH_TIME_END_HOUR); - if (readableArray == null || startHour == 0 || endHour == 0) { + ReadableArray readableArray = readableMap.getArray(JConstants.PUSH_TIME_DAYS); + if (readableArray == null + || !readableMap.hasKey(JConstants.PUSH_TIME_START_HOUR) + || !readableMap.hasKey(JConstants.PUSH_TIME_END_HOUR)) { JLogger.w(JConstants.PARAMS_NULL); return; } + int startHour = readableMap.getInt(JConstants.PUSH_TIME_START_HOUR); + int endHour = readableMap.getInt(JConstants.PUSH_TIME_END_HOUR);
230-244: Allow 0 in setSilenceTime; avoid false negatives.- int startHour = readableMap.getInt(JConstants.SILENCE_TIME_START_HOUR); - int startMinute = readableMap.getInt(JConstants.SILENCE_TIME_START_MINUTE); - int endHour = readableMap.getInt(JConstants.SILENCE_TIME_END_HOUR); - int endMinute = readableMap.getInt(JConstants.SILENCE_TIME_END_MINUTE); - if (startHour == 0 || startMinute == 0 || endHour == 0 || endMinute == 0) { + if (!readableMap.hasKey(JConstants.SILENCE_TIME_START_HOUR) + || !readableMap.hasKey(JConstants.SILENCE_TIME_START_MINUTE) + || !readableMap.hasKey(JConstants.SILENCE_TIME_END_HOUR) + || !readableMap.hasKey(JConstants.SILENCE_TIME_END_MINUTE)) { JLogger.w(JConstants.PARAMS_NULL); return; } + int startHour = readableMap.getInt(JConstants.SILENCE_TIME_START_HOUR); + int startMinute = readableMap.getInt(JConstants.SILENCE_TIME_START_MINUTE); + int endHour = readableMap.getInt(JConstants.SILENCE_TIME_END_HOUR); + int endMinute = readableMap.getInt(JConstants.SILENCE_TIME_END_MINUTE);
662-674: Wrong log key when NOTIFICATION_ID is missing.Logs GEO_FENCE_ID by mistake.
- JLogger.w("there are no " + JConstants.GEO_FENCE_ID); + JLogger.w("there are no " + JConstants.NOTIFICATION_ID);ios/RCTJPushModule/RCTJPushModule.m (2)
6-20: Remove duplicate BADGE macro.BADGE is defined twice (Lines 6 and 17).
-#define BADGE @"badge"
128-135: setDebugMode can’t turn logging off.Handle both states.
RCT_EXPORT_METHOD(setDebugMode: (BOOL )enable) { - if(enable){ - [JPUSHService setDebugMode]; - } + if (enable) { + [JPUSHService setDebugMode]; + } else { + [JPUSHService setLogOFF]; + } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge base: Disabled due to data retention organization setting
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (5)
-
android/libs/jpush-android-4.8.0.jaris excluded by!**/*.jar -
android/libs/jpush-android-5.9.0.jaris excluded by!**/*.jar -
example/android/app/src/main/res/drawable/jpush_notification_icon.pngis excluded by!**/*.png -
example/android/gradle/wrapper/gradle-wrapper.jaris excluded by!**/*.jar -
example/ios/Podfile.lockis excluded by!**/*.lock
📒 Files selected for processing (84)
-
.npmignore(1 hunks) -
JPushRN.podspec(2 hunks) -
android/build.gradle(1 hunks) -
android/src/main/AndroidManifest.xml(5 hunks) -
android/src/main/java/cn/jiguang/plugins/push/JPushModule.java(6 hunks) -
android/src/main/java/cn/jiguang/plugins/push/common/JConstants.java(3 hunks) -
android/src/main/java/cn/jiguang/plugins/push/helper/JPushHelper.java(3 hunks) -
android/src/main/java/cn/jiguang/plugins/push/receiver/JPushModuleReceiver.java(4 hunks) -
android/src/main/res/drawable/jpush_btn_blue_bg.xml(1 hunks) -
android/src/main/res/drawable/jpush_btn_grey_bg.xml(1 hunks) -
android/src/main/res/drawable/jpush_cancel_btn_bg.xml(1 hunks) -
android/src/main/res/drawable/jpush_close.xml(1 hunks) -
android/src/main/res/drawable/jpush_contain_bg.xml(1 hunks) -
android/src/main/res/drawable/jpush_interstitial_bg.xml(1 hunks) -
android/src/main/res/layout/jpush_banner.xml(1 hunks) -
android/src/main/res/layout/jpush_full.xml(1 hunks) -
android/src/main/res/layout/jpush_interstitial.xml(1 hunks) -
cursor.md(1 hunks) -
example/.buckconfig(0 hunks) -
example/.bundle/config(1 hunks) -
example/.eslintrc.js(1 hunks) -
example/.flowconfig(0 hunks) -
example/.gitattributes(0 hunks) -
example/.gitignore(2 hunks) -
example/.prettierrc.js(1 hunks) -
example/.watchmanconfig(1 hunks) -
example/App.js(1 hunks) -
example/Gemfile(1 hunks) -
example/README.md(1 hunks) -
example/__tests__/App.test.tsx(1 hunks) -
example/android/.project(0 hunks) -
example/android/.settings/org.eclipse.buildship.core.prefs(0 hunks) -
example/android/app/build.gradle(1 hunks) -
example/android/app/src/debug/AndroidManifest.xml(1 hunks) -
example/android/app/src/main/AndroidManifest.xml(1 hunks) -
example/android/app/src/main/java/com/example/MainActivity.java(0 hunks) -
example/android/app/src/main/java/com/example/MainActivity.kt(1 hunks) -
example/android/app/src/main/java/com/example/MainApplication.java(0 hunks) -
example/android/app/src/main/java/com/example/MainApplication.kt(1 hunks) -
example/android/app/src/main/res/drawable/rn_edit_text_material.xml(1 hunks) -
example/android/app/src/main/res/values/styles.xml(1 hunks) -
example/android/build.gradle(1 hunks) -
example/android/gradle.properties(1 hunks) -
example/android/gradle/wrapper/gradle-wrapper.properties(1 hunks) -
example/android/gradlew(3 hunks) -
example/android/gradlew.bat(4 hunks) -
example/android/settings.gradle(1 hunks) -
example/app.json(1 hunks) -
example/babel.config.js(1 hunks) -
example/ios-swift/AppDelegate.swift(1 hunks) -
example/ios-swift/HelloWord-Bridging-Header.h(1 hunks) -
example/ios-swift/README.md(1 hunks) -
example/ios/.xcode.env(1 hunks) -
example/ios/Podfile(1 hunks) -
example/ios/example.xcodeproj/project.pbxproj(12 hunks) -
example/ios/example.xcodeproj/xcshareddata/xcschemes/example-tvOS.xcscheme(0 hunks) -
example/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme(1 hunks) -
example/ios/example.xcworkspace/contents.xcworkspacedata(0 hunks) -
example/ios/example.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist(0 hunks) -
example/ios/example/AppDelegate.h(1 hunks) -
example/ios/example/AppDelegate.mm(4 hunks) -
example/ios/example/Base.lproj/LaunchScreen.xib(0 hunks) -
example/ios/example/Images.xcassets/AppIcon.appiconset/Contents.json(1 hunks) -
example/ios/example/Info.plist(1 hunks) -
example/ios/example/LaunchScreen.storyboard(1 hunks) -
example/ios/example/PrivacyInfo.xcprivacy(1 hunks) -
example/ios/example/main.m(1 hunks) -
example/ios/exampleTests/Info.plist(1 hunks) -
example/ios/exampleTests/exampleTests.m(1 hunks) -
example/jest.config.js(1 hunks) -
example/metro.config.js(1 hunks) -
example/package.json(1 hunks) -
example/tsconfig.json(1 hunks) -
index.d.ts(5 hunks) -
index.js(8 hunks) -
ios/RCTJPushModule.xcodeproj/project.pbxproj(3 hunks) -
ios/RCTJPushModule/RCTJPushModule.m(11 hunks) -
ios/RCTJPushModule/jpush-ios-5.9.0.xcframework/Info.plist(1 hunks) -
ios/RCTJPushModule/jpush-ios-5.9.0.xcframework/ios-arm64/Headers/JPUSHService.h(29 hunks) -
ios/RCTJPushModule/jpush-ios-5.9.0.xcframework/ios-arm64/PrivacyInfo.xcprivacy(1 hunks) -
ios/RCTJPushModule/jpush-ios-5.9.0.xcframework/ios-arm64_x86_64-simulator/Headers/JPUSHService.h(1 hunks) -
ios/RCTJPushModule/jpush-ios-5.9.0.xcframework/ios-arm64_x86_64-simulator/PrivacyInfo.xcprivacy(1 hunks) -
package.json(1 hunks) -
rm.txt(1 hunks)
💤 Files with no reviewable changes (11)
- example/android/.settings/org.eclipse.buildship.core.prefs
- example/android/.project
- example/ios/example.xcworkspace/contents.xcworkspacedata
- example/ios/example.xcodeproj/xcshareddata/xcschemes/example-tvOS.xcscheme
- example/.flowconfig
- example/ios/example/Base.lproj/LaunchScreen.xib
- example/android/app/src/main/java/com/example/MainApplication.java
- example/.buckconfig
- example/.gitattributes
- example/android/app/src/main/java/com/example/MainActivity.java
- example/ios/example.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
🧰 Additional context used
🪛 Clang (14.0.6)
example/ios-swift/HelloWord-Bridging-Header.h
[error] 12-12: 'JPUSHService.h' file not found
(clang-diagnostic-error)
example/ios/example/AppDelegate.h
[error] 1-1: 'RCTAppDelegate.h' file not found
(clang-diagnostic-error)
ios/RCTJPushModule/jpush-ios-5.9.0.xcframework/ios-arm64_x86_64-simulator/Headers/JPUSHService.h
[error] 14-14: 'Foundation/Foundation.h' file not found
(clang-diagnostic-error)
[warning] 37-37: variable 'kJPFNetworkIsConnectingNotification' provides global access to a non-const object; consider making the pointed-to data 'const'
(cppcoreguidelines-avoid-non-const-global-variables)
[warning] 38-38: variable 'kJPFNetworkDidSetupNotification' provides global access to a non-const object; consider making the pointed-to data 'const'
(cppcoreguidelines-avoid-non-const-global-variables)
[warning] 39-39: variable 'kJPFNetworkDidCloseNotification' provides global access to a non-const object; consider making the pointed-to data 'const'
(cppcoreguidelines-avoid-non-const-global-variables)
[warning] 40-40: variable 'kJPFNetworkDidRegisterNotification' provides global access to a non-const object; consider making the pointed-to data 'const'
(cppcoreguidelines-avoid-non-const-global-variables)
[warning] 41-41: variable 'kJPFNetworkFailedRegisterNotification' provides global access to a non-const object; consider making the pointed-to data 'const'
(cppcoreguidelines-avoid-non-const-global-variables)
[warning] 42-42: variable 'kJPFNetworkDidLoginNotification' provides global access to a non-const object; consider making the pointed-to data 'const'
(cppcoreguidelines-avoid-non-const-global-variables)
[warning] 43-43: variable 'kJPFNetworkDidReceiveMessageNotification' provides global access to a non-const object; consider making the pointed-to data 'const'
(cppcoreguidelines-avoid-non-const-global-variables)
[warning] 44-44: variable 'kJPFServiceErrorNotification' provides global access to a non-const object; consider making the pointed-to data 'const'
(cppcoreguidelines-avoid-non-const-global-variables)
[warning] 46-46: 2 adjacent parameters of 'NS_OPTIONS' of similar type ('int') are easily swapped by mistake
(bugprone-easily-swappable-parameters)
[note] 46-46: the first parameter in the range is 'NSUInteger'
(clang)
[note] 46-46: the last parameter in the range is 'JPAuthorizationOptions'
(clang)
[warning] 58-58: 2 adjacent parameters of 'NS_ENUM' of similar type ('int') are easily swapped by mistake
(bugprone-easily-swappable-parameters)
[note] 58-58: the first parameter in the range is 'NSUInteger'
(clang)
[note] 58-58: the last parameter in the range is 'JPAuthorizationStatus'
(clang)
[warning] 427-427: variable 'NSSet' is non-const and globally accessible, consider making it const
(cppcoreguidelines-avoid-non-const-global-variables)
[warning] 636-636: variable 'UILocalNotification' is non-const and globally accessible, consider making it const
(cppcoreguidelines-avoid-non-const-global-variables)
[warning] 653-653: variable 'UILocalNotification' is non-const and globally accessible, consider making it const
(cppcoreguidelines-avoid-non-const-global-variables)
[warning] 695-695: variable 'NSArray' is non-const and globally accessible, consider making it const
(cppcoreguidelines-avoid-non-const-global-variables)
[warning] 725-725: variable 'BOOL' is non-const and globally accessible, consider making it const
(cppcoreguidelines-avoid-non-const-global-variables)
[warning] 764-764: variable 'NSString' is non-const and globally accessible, consider making it const
(cppcoreguidelines-avoid-non-const-global-variables)
ios/RCTJPushModule/jpush-ios-5.9.0.xcframework/ios-arm64/Headers/JPUSHService.h
[error] 14-14: 'Foundation/Foundation.h' file not found
(clang-diagnostic-error)
🪛 Gitleaks (8.28.0)
example/android/app/build.gradle
[high] 86-86: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
🪛 LanguageTool
cursor.md
[uncategorized] ~30-~30: 动词的修饰一般为‘形容词(副词)+地+动词’。您的意思是否是:最新"地"插
Context: ...ample/package.json 中 修改示例 插件的集成版本号。 改为最新的插件版本号。涉及到更改的代码 ``` "dependen...
(wb4)
example/README.md
[style] ~5-~5: Consider using the more formal “until”.
Context: ...ev/docs/environment-setup) instructions till "Creating a new application" step, befo...
(TILL)
🪛 markdownlint-cli2 (0.18.1)
example/ios-swift/README.md
1-1: First line in a file should be a top-level heading
(MD041, first-line-heading, first-line-h1)
11-11: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
23-23: Ordered list item prefix
Expected: 1; Actual: 2; Style: 1/1/1
(MD029, ol-prefix)
cursor.md
2-2: First line in a file should be a top-level heading
(MD041, first-line-heading, first-line-h1)
11-11: Trailing spaces
Expected: 0 or 2; Actual: 3
(MD009, no-trailing-spaces)
12-12: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
14-14: Trailing spaces
Expected: 0 or 2; Actual: 3
(MD009, no-trailing-spaces)
16-16: Trailing spaces
Expected: 0 or 2; Actual: 3
(MD009, no-trailing-spaces)
17-17: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
19-19: Trailing spaces
Expected: 0 or 2; Actual: 3
(MD009, no-trailing-spaces)
21-21: Trailing spaces
Expected: 0 or 2; Actual: 4
(MD009, no-trailing-spaces)
32-32: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
example/README.md
1-1: First line in a file should be a top-level heading
(MD041, first-line-heading, first-line-h1)
🪛 RuboCop (1.81.1)
example/Gemfile
[convention] 9-9: Gems should be sorted in an alphabetical order within their section of the Gemfile. Gem activesupport should appear before cocoapods.
(Bundler/OrderedGems)
JPushRN.podspec
[convention] 5-6: Extra empty line detected at block body beginning.
(Layout/EmptyLinesAroundBlockBody)
example/ios/Podfile
[convention] 6-6: Put a comma after the last item of a multiline array.
(Style/TrailingCommaInArrayLiteral)
[convention] 36-36: Avoid comma after the last parameter of a method call.
(Style/TrailingCommaInArguments)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Socket Security: Pull Request Alerts
🔇 Additional comments (68)
example/ios/example/main.m (1)
5-6: Clean formatting update.The signature refactor and brace placement follow standard Objective-C conventions. No behavioral changes; purely stylistic.
example/ios/example/Images.xcassets/AppIcon.appiconset/Contents.json (1)
1-53: Cosmetic key reordering—no functional impact.JSON key order doesn't affect behavior or semantics. This reordering is purely a formatting change, likely from Xcode auto-formatting. No changes needed.
example/android/gradle.properties (5)
12-13: Good: JVM args upgraded to modern standards.MaxMetaspaceSize replaces the deprecated MaxPermSize (removed in Java 8), and the heap/metaspace increase (512m→2048m for heap, 256m→512m for metaspace) is appropriate for React Native builds.
20-25: Good: AndroidX is now required for modern Android development.These settings enable AndroidX support and automatic library conversion via Jetifier—essential for current Android tooling and dependency compatibility.
27-30: Comprehensive architecture coverage.The four-architecture setup (armeabi-v7a, arm64-v8a, x86, x86_64) covers production devices (arm variants) and emulators (x86 variants). CLI override is possible via
-PreactNativeArchitectures=...if needed.
32-37: New Architecture disabled—consider aligning with modernization goals.The setting defaults to
newArchEnabled=false, which skips Fabric and TurboModules. Since the PR modernizes the build system, verify whether new architecture support should be enabled for the example app or left disabled by design.
39-41: Good: Hermes engine improves performance.Switching from JSC to Hermes is a sound performance optimization for React Native. Ensure downstream dependencies and testing validate this choice.
example/android/app/src/main/res/drawable/rn_edit_text_material.xml (1)
1-37: Clean drawable resource implementation.The inset wrapper and selector logic look solid. The comment thoroughly documents why the removed item was necessary—good defensive coding for future maintainers.
example/android/app/src/main/res/values/styles.xml (1)
4-6: Smart theme and styling updates.The DayNight parent enables dark mode support automatically. Replacing hardcoded textColor with the editTextBackground drawable gives you proper state management and Material Design alignment. Changes work together well.
example/tsconfig.json (1)
1-3: No issue found. The dependency exists.The
@react-native/typescript-configpackage is listed inexample/package.jsonas a devDependency (version 0.74.83). The tsconfig.json will resolve the extended config correctly.example/metro.config.js (1)
1-11: Modern Metro config pattern—looks good.This update follows current React Native best practices. The empty config delegates to defaults, which is ideal for an example app. Shows users the standard setup.
example/ios/.xcode.env (1)
1-11: Standard React Native boilerplate—looks good.This file correctly sets up the Xcode environment for build phases. The
command -v nodeapproach is idiomatic and will work as expected.One optional improvement: If node isn't in PATH,
NODE_BINARYwill be empty and builds will fail. You could add a fallback or validation, but that's atypical for this type of config file. The current approach matches React Native conventions.example/.eslintrc.js (1)
3-3: LGTM! Updated to official preset.The change correctly updates to
@react-native/eslint-config, the official ESLint config for React Native with the latest version being 0.81.1. This replaces the legacy@react-native-communitypackage, aligning with modern React Native tooling.example/ios/exampleTests/exampleTests.m (2)
16-27: LGTM!The recursive subview finder is implemented correctly. Standard pattern for traversing the view hierarchy.
29-64: Standard React Native test implementation looks good.The test correctly:
- Captures RedBox errors in DEBUG mode
- Polls the UI with run loop pumping
- Asserts both error-free execution and element presence
Minor: Line 63 uses
%dforTIMEOUT_SECONDS. Works fine but will display "600 seconds" (or "30 seconds" after fixing the timeout).example/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme (1)
6-6: LGTM—parallel builds enabled.Good practice. Minimal impact with a single target, but aligns with modern Xcode defaults.
example/ios/example/AppDelegate.mm (3)
17-18: LGTM: Import added for JPush SDK.The import is necessary for the JPUSHService API calls used throughout the file.
23-26: LGTM: Clean delegate protocol conformance.Using a private extension for the JPUSHRegisterDelegate protocol follows iOS best practices.
58-58: No issues found with the API change.The
jsBundleURLForBundleRoot:@"index"call is correct for React Native 0.74.1. This single-parameter format matches the current API; earlier versions required afallbackResourceparameter. Only one usage exists in the codebase, so no other files need updates.ios/RCTJPushModule/jpush-ios-5.9.0.xcframework/ios-arm64_x86_64-simulator/PrivacyInfo.xcprivacy (1)
1-23: Simulator and device manifests are identical.The simulator framework privacy manifest matches the device version exactly. This is expected and correct.
ios/RCTJPushModule/jpush-ios-5.9.0.xcframework/ios-arm64/PrivacyInfo.xcprivacy (1)
1-23: Privacy manifest structure looks good.NSPrivacyTracking is false, no data collection declared, and UserDefaults API usage is documented. This aligns with iOS privacy requirements for SDK distribution.
example/ios/example/PrivacyInfo.xcprivacy (1)
1-37: Privacy manifest reason codes verified as correct.The three reason codes (C617.1, CA92.1, 35F9.1) are valid and correctly match their API categories: file timestamp access, UserDefaults operations, and system boot time measurement respectively.
example/ios-swift/AppDelegate.swift (2)
27-27: Check module name spelling."HelloWord" looks like a typo for "HelloWorld". Verify this is intentional.
55-67: Bundle configuration is correct.Dev/production bundle URL logic follows React Native best practices.
example/ios/example/Info.plist (2)
20-20: Good move: versioning via build settings.Using
$(MARKETING_VERSION) and $ (CURRENT_PROJECT_VERSION) keeps Info.plist clean and CI-friendly.Also applies to: 24-24
40-40: Targeting arm64 only is fine.Matches modern devices and RN toolchains.
example/ios/example.xcodeproj/project.pbxproj (3)
12-12: AppDelegate.m → .mm is the right call for RN 0.74/Hermes.Matches modern RN templates and C++ interop.
Also applies to: 36-36
54-61: New test target wiring looks correct.Frameworks/Sources/Resources phases and host app linkage are set up properly.
Also applies to: 392-398, 160-181
248-254: LaunchScreen.xib → storyboard is a good modernization.Reduces legacy warnings and matches current templates.
Also applies to: 17-17
example/.watchmanconfig (1)
1-1: LGTM!Standard empty watchman config with proper newline.
example/app.json (1)
4-4: LGTM!Trailing newline follows best practices.
example/__tests__/App.test.tsx (1)
9-11: LGTM!Explicit Jest import with clear explanation improves type safety and follows modern Jest best practices.
example/ios-swift/HelloWord-Bridging-Header.h (1)
12-12: No action needed. Import paths are correct.The headers exist at their expected locations. JPUSHService.h is found in the xcframework, and RCTJPushModule.h is in place. The import statements will resolve correctly. The code is fine as-is.
Likely an incorrect or invalid review comment.
.npmignore (1)
1-2: Remove this review comment—it's based on an incorrect assumption.The review flags concern about "removing
example/from.npmignore," butexample/remains in.npmignore(visible in the snippet). Withexample/listed, the directory stays excluded from the npm package. No package size increase occurs. The only actual change shown is addingcursor.mdto.npmignore.Likely an incorrect or invalid review comment.
package.json (1)
9-9: Provide a CHANGELOG or migration guide for the jpush-react-native 3.x upgrade.The version bump from 2.9.2 to 3.2.1 is a major version change and follows semantic versioning. However, users upgrading to v3.x need documented breaking changes and migration instructions. Ensure a CHANGELOG or migration guide is included in this release.
example/.prettierrc.js (1)
2-3: LGTM! Prettier config modernized.The update replaces deprecated
jsxBracketSameLinewithbracketSameLineand addsarrowParens. These align with current Prettier standards.example/.bundle/config (1)
1-2: LGTM! Standard Bundler configuration.The config isolates gems to
vendor/bundleand forces Ruby platform builds. This prevents native extension conflicts across environments.android/build.gradle (3)
8-8: LGTM! Compile SDK updated to Android 14.The update to SDK 34 brings the build system current with Android 14 requirements.
10-10: LGTM! Namespace added for modern Gradle compatibility.The namespace declaration is required for Android Gradle Plugin 8.0+ and follows best practices.
13-14: Remove the unverified claim about prior minSdk value.The review assumes minSdkVersion was previously 16, but git history provides no evidence of this. The earliest commit doesn't contain
android/build.gradleat all.What's accurate: Setting minSdkVersion to 23 does drop support for Android versions below 6.0 (API 23). What's not verified: That it was previously 16.
The codebase contains no CHANGELOG or MIGRATION documentation, so there's no record of when or why this decision was made. If this change is recent, document it; if it's legacy configuration, the concern becomes moot.
Likely an incorrect or invalid review comment.
example/jest.config.js (1)
1-3: LGTM! Standard React Native Jest config.The preset provides sensible defaults for React Native testing.
example/babel.config.js (1)
2-2: LGTM! Babel preset updated for modern React Native.The preset name reflects React Native's package reorganization to the
@react-nativescope. This aligns with current RN tooling standards.example/android/app/src/debug/AndroidManifest.xml (1)
5-8: LGTM! Removed unnecessary debug permission.The removal of
SYSTEM_ALERT_WINDOWreduces the permission footprint in debug builds. The application tag formatting is cosmetic.example/.gitignore (1)
23-74: LGTM — broader, safer ignoresNice additions for Pods, Yarn, Metro, coverage, and Android artifacts.
example/android/settings.gradle (1)
4-4: Move to RN Gradle plugin — goodThis matches RN 0.74’s build flow. Ensure app/build.gradle applies the React plugin (com.facebook.react) and that autolinking resolves JPush modules without manual includes.
example/ios/Podfile (2)
11-15: Use frameworks toggle carefullyDynamic frameworks can cause duplicate symbol issues with some pods. Keeping linkage behind USE_FRAMEWORKS is good; default to static unless you need dynamic.
17-29: iOS target names verified—Podfile matches Xcode projectThe "example" target exists in the Xcode project and matches the Podfile declaration. Both the main target and nested "exampleTests" target are correctly named. Pod install will succeed.
example/package.json (2)
35-37: <!-- [scratchpad_update]
[observations]
- Search results do not explicitly state RN 0.74's exact Node engine in package.json
- Result 9 confirms: "Starting from React Native 0.73, Node.js version 18 or higher is required"
- Result 1: dependencies starting RN >0.72 require Node 18
- Result 6: Shows @react-native packages require >=18 (as of 0.72.5)
- Result 10: Shows Node 18.20.3 used with RN 0.74.1 (example, not the minimum requirement)
- None of the sources explicitly confirm >=18.17 vs >=18
[pending]
- Could not find exact RN 0.74 package.json engine field declaration
- Need to search more specifically for RN 0.74's package.json or npm registry entry
[scratchpad_end] --><!-- [scratchpad_update_2]
[observations]- Result 15 shows upgrade guide from 0.74.0 to 0.76.5 with "node": ">=18"
- Still no explicit confirmation that RN 0.74 specifically requires >=18 vs >=18.17
- Result 12 reiterates >=18 minimum for packages (from earlier search)
- The search results confirm >=18, but not the specific >=18.17 patch version requirement
[pending]
- Search the npm registry directly for [email protected] package.json
- Or search for RN 0.74 GitHub release or official upgrade guide with exact Node requirement
[actions]
- Do one more targeted search for "[email protected]" npm registry or GitHub release notes
[scratchpad_end] --><!-- [scratchpad_final]
[task verify_rn_0.74_node_engine_requirement][observations]
- Result 23 is the OFFICIAL React Native releases support matrix
- Shows RN 0.74: Node min = 18 (NOT 18.17)
- This directly contradicts the original review suggestion to use >=18.17
- No mention of patch-level requirement like 18.17
[analysis]
- The review comment claims "RN 0.74 generally targets Node 18 LTS (often 18.17+)"
- But official RN support matrix clearly shows Node 18 minimum, with no patch-level specification
=18 is technically correct per official RN 0.74 requirements
- Suggesting >=18.17 as a "tighten" is not supported by the official baseline requirement
[conclusion]
- The original review comment's suggestion is INCORRECT
- The official RN 0.74 requirement is "node": "18" (minimum major.minor)
- The current code ">=18" is ALREADY correct and matches RN 0.74 requirements
- The suggested change to >=18.17 is unnecessary and not based on RN 0.74's actual engine requirement
- This is an incorrect review comment that should be dismissed
[tag]
[scratchpad_end] -->
Disregard this review comment.
React Native 0.74 requires Node 18 minimum, not 18.17. The current
">=18"engine specification already meets RN 0.74's baseline and requires no change.Likely an incorrect or invalid review comment.
19-33: Remove Babel/ESLint/TypeScript upgrade suggestionsYour current versions satisfy RN 0.74's peer dependencies. @react-native/[email protected] requires @babel/core: '*' (any version), and @react-native/[email protected] requires eslint: '>=8' and prettier: '>=2'. Your package.json already meets these constraints: Babel 7.20.0, ESLint 8.19.0, and TypeScript 5.0.4 all work with RN 0.74. No upgrade is required.
Likely an incorrect or invalid review comment.
example/android/app/build.gradle (2)
102-108: Release uses debug keystore.OK for the example app, but don’t ship like this. Add a real release signingConfig before publishing.
113-115: Good: use react-android BOM’d dependency.Using
implementation("com.facebook.react:react-android")lets RNGP resolve the correct version from package.json. Keep it. (reactnative.dev)ios/RCTJPushModule/jpush-ios-5.9.0.xcframework/ios-arm64_x86_64-simulator/Headers/JPUSHService.h (1)
232-237: ATT/IDFA compliance check.If you ever pass a non‑nil advertisingIdentifier here, ensure you present the AppTrackingTransparency prompt and include NSUserTrackingUsageDescription. Otherwise App Review may reject.
JPushRN.podspec (2)
21-21: Framework migration looks correct.The switch from
vendored_libraries(static .a) tovendored_frameworks(xcframework) aligns with the iOS SDK upgrade to 5.9.0.
6-6: Review comment is inaccurate—no pod name change occurs in this PR.The pod name has been
"JPushRN"since at least v3.1.8. Git history shows this name persisted through all recent versions. The current PR (v3.2.1) maintains this existing name—it doesn't introduce a change from"JPush"to"JPushRN". No breaking change exists here.Likely an incorrect or invalid review comment.
ios/RCTJPushModule.xcodeproj/project.pbxproj (2)
6-6: Xcode project format updated.
objectVersionbumped from 46 to 52 (Xcode 12+ format). This is expected for xcframework support.
12-12: Verify JCore framework version compatibility and build architecture settings.Code inspection confirms the module correctly implements JPush 5.9.0 APIs—completion handlers, new setBackgroundEnable method, and proper iOS version checks are all present. No deprecated method invocations found.
However, JPush 5.9.0 requires JCore >= 5.2.0, and your project references
jcore-react-nativebut the version is not visible in the repository. Additionally, armv7/armv7s architectures must be removed for this SDK version.Before merging, manually confirm:
- JCore xcframework version is 5.2.0 or newer
- Build settings don't include armv7/armv7s (check VALID_ARCHS)
- Test push registration and receipt flows on a physical device
android/src/main/res/drawable/jpush_close.xml (1)
1-19: LGTM for the vector asset.No issues found. Matches intended size and colors.
index.d.ts (3)
63-67: LGTM: init params now use channel.The rename looks good.
301-317: OK: listener rename.
addCustomMessageListenersignature looks consistent.
351-382: Fix the typo, but verify native payload structure matches the type definition.The typo is real:
mesageId→messageIdat index.d.ts:356. Fix it.However, JPush typically exposes message IDs via
_j_msgidon iOS andEXTRA_MSG_IDin Android extras, not as a top-level field. The type definition claims fields likemessageId,title,content,target, andclickAction— but these don't match standard JPush payload structure.Since index.js passes the native event payload through directly without transformation, verify that:
- The native bridge actually emits all these fields
- Field names align with what the native JPush SDK sends
- Tests validate the actual payload structure received
The spelling fix is straightforward. The structural alignment requires inspecting the native implementation.
example/android/app/src/main/java/com/example/MainActivity.kt (1)
20-21: Code matches React Native 0.74.1 expectations.The DefaultReactActivityDelegate constructor signature for RN 0.74.1 is
DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled), which matches the code on lines 20-21. The earlier concern about requiring two booleans (fabricEnabled and concurrentRoot) applies to older versions—RN 0.74.1 uses only fabricEnabled.The JS component name "example" is confirmed in line 14's
getMainComponentName()return value and registered in package.json and app.json.android/src/main/java/cn/jiguang/plugins/push/helper/JPushHelper.java (2)
45-55: Unable to verify review comment fully without codebase access.The web search confirmed that JPush API design includes extras as JSON objects rather than strings, aligning with the review's concern. However, I cannot locate the actual TypeScript type definitions in
index.d.tsor verify the current codebase structure, usage patterns, and potential breaking changes to consumers ofconvertInAppMessageToMap.To proceed with this review:
- Verify that
index.d.tsactually definesextras: Extra(object type) andtarget: string[]- Search for all calls to
convertInAppMessageToMapto assess breaking change impact- Check if consumers already handle object/array types or expect strings
- Confirm whether JSON constants (
INAPPEXTRAS,INAPPSHOWTARGET) are referenced elsewhere in the codebase
76-90: <!-- Based on extensive web searches, I cannot find public getter method names for JPush Android SDK's NotificationCustomButton class in official documentation or source repositories. The searches show:
- JPush uses ProGuard obfuscation with explicit "keep" rules for cn.jpush.** classes
- Official GitHub samples exist but don't contain NotificationCustomButton source
- The obfuscated fields (a-f) are consistent with standard ProGuard behavior
- No public API documentation lists these specific getter methods
The review comment is based on assumptions about public getters that cannot be verified. I should mark this for verification by the developer. -->
Verify if public getter methods exist on JPush Android SDK's NotificationCustomButton.
The review suggests using
getMsgId(),getPlatform(),getName(),getActionType(),getAction(), andgetData(), but I couldn't confirm these public getter methods in official JPush Android SDK documentation or source repositories.The SDK uses ProGuard obfuscation, which explains the obfuscated field names. Without verification that these specific public getters exist and are stable across SDK versions, it's uncertain whether the suggested fix is correct or if obfuscated field access is intentional.
android/src/main/res/layout/jpush_interstitial.xml (1)
62-73: Scrollable body may not scroll.A TextView with scrollbars won’t scroll by itself unless you set a movement method in code. Prefer wrapping the text block in a NestedScrollView to guarantee scroll for long content.
example/android/app/src/main/java/com/example/MainApplication.kt (1)
29-30: Verify BuildConfig flags.Confirm your RN template defines IS_NEW_ARCHITECTURE_ENABLED and IS_HERMES_ENABLED. Some versions use different names.
Also applies to: 39-39
example/android/app/src/main/AndroidManifest.xml (1)
3-3: I'll verify the core claims and check the codebase structure.Based on my verification using official Android and Flutter documentation:
Android 13 (API level 33) and higher supports a runtime permission for sending non-exempt notifications: POST_NOTIFICATIONS. If a user installs your app on a device that runs Android 13 or higher, your app's notifications are off by default. Your app must wait to send notifications until after you request the new permission and the user grants that permission to your app.
The review comment is accurate. The manifest declaration is necessary but insufficient—flutter_local_notifications plugin v16 onwards only specifies these POST_NOTIFICATIONS and VIBRATE permissions. This means dependencies may already contribute to manifest merging, but explicit runtime request code must still be implemented.
Add POST_NOTIFICATIONS permission to manifest and implement runtime request.
If your app targets Android 13 or higher, your app has complete control over when the permission dialog is displayed. Use this opportunity to explain to users why the app needs this permission, encouraging them to grant it. The diff is correct. After adding the manifest entry, ensure runtime permission logic (via ActivityCompat.requestPermissions or permission_handler package) is implemented to trigger the permission dialog at an appropriate point in the app flow.
android/src/main/AndroidManifest.xml (1)
113-118: InitProvider permissions look good.authorities scoped to ${applicationId}, exported=false, guarded by JPUSH_MESSAGE perms. LGTM.
android/src/main/java/cn/jiguang/plugins/push/common/JConstants.java (1)
70-88: Constants additions look consistent with the new API surface.Names align across platforms (pros/inapp events). No issues.
|
|
||
| 使用方法:修改需求里的内容,将需求和步骤内容作为指令让cursor进行执行。 | ||
|
|
||
|
|
||
| 需求: | ||
| 1. 更新iOS JPush SDK 到 x.x.x 版本。JPush SDK 包的路径是:xxx | ||
| 2. 更新Android JPush SDK 到 x.x.x 版本, JPush SDK 包的路径是:xxx | ||
| 3. 将原生iOS、Android SDK 新增的方法,封装在插件中。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a clear title and context
Start with an H1 so readers know this is the JPush upgrade playbook.
+
+# JPush SDK 升级执行手册
+
使用方法:修改需求里的内容,将需求和步骤内容作为指令让cursor进行执行。📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 使用方法:修改需求里的内容,将需求和步骤内容作为指令让cursor进行执行。 | |
| 需求: | |
| 1. 更新iOS JPush SDK 到 x.x.x 版本。JPush SDK 包的路径是:xxx | |
| 2. 更新Android JPush SDK 到 x.x.x 版本, JPush SDK 包的路径是:xxx | |
| 3. 将原生iOS、Android SDK 新增的方法,封装在插件中。 | |
| # JPush SDK 升级执行手册 | |
| 使用方法:修改需求里的内容,将需求和步骤内容作为指令让cursor进行执行。 | |
| 需求: | |
| 1. 更新iOS JPush SDK 到 x.x.x 版本。JPush SDK 包的路径是:xxx | |
| 2. 更新Android JPush SDK 到 x.x.x 版本, JPush SDK 包的路径是:xxx | |
| 3. 将原生iOS、Android SDK 新增的方法,封装在插件中。 |
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
2-2: First line in a file should be a top-level heading
(MD041, first-line-heading, first-line-h1)
🤖 Prompt for AI Agents
In cursor.md around lines 1 to 8, the document lacks a clear title and context;
add an H1 at the top like "JPush SDK Upgrade Playbook" and a short introductory
paragraph that explains the purpose (upgrading iOS and Android JPush SDKs and
wrapping new native methods in the plugin), then keep the existing numbered
requirements and usage instructions below the new heading so readers immediately
understand the document intent and scope.
| ``` | ||
| ``` | ||
|
|
||
| Android: | ||
|
|
||
| ``` | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Specify languages for code fences
Label empty examples so linters pass and future snippets render well (MD040).
- ```
+ ```swift@@
<details>
<summary>🧰 Tools</summary>
<details>
<summary>🪛 markdownlint-cli2 (0.18.1)</summary>
12-12: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
---
14-14: Trailing spaces
Expected: 0 or 2; Actual: 3
(MD009, no-trailing-spaces)
---
16-16: Trailing spaces
Expected: 0 or 2; Actual: 3
(MD009, no-trailing-spaces)
---
17-17: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
</details>
</details>
<details>
<summary>🤖 Prompt for AI Agents</summary>
In cursor.md around lines 12 to 18 the code fences are empty and unlabeled which
trips markdown linters (MD040); update the empty fenced code blocks to include
language identifiers and label the empty examples as suggested — replace the
first empty block with swift and the second with java (or add a brief
comment inside each block indicating it's intentionally empty) so linters and
renderers treat them as valid labeled code fences.
</details>
<!-- fingerprinting:phantom:medusa:chinchilla -->
<!-- This is an auto-generated comment by CodeRabbit -->
| 1. 找到需要升级的iOS JPush SDK,替换ios/RCTJPushModule/jpush-ios-x.x.x.xcframework 为需要更新的版本。 | ||
| 2. 将/ios/RCTJPushModule.xcodeproj/project.pbxproj中关于jpush-ios-x.x.x.xcframework中引用路径的代码,替换为需要更新的版本。 | ||
| 3. 找到需要升级的Android JPush SDK,替换android/libs/jpush-android-x.x.x.jar 为需要更新的版本。 | ||
| 4. 在插件中封装需求中需要封装的SDK方法,并在插件示例demo中提供示例调用代码,注意rn插件新增方法还需要再index.js和index.d.ts文件中声明哦。(如果没有需求中没有需要新增的方法,则跳过该步骤) | ||
| 5. 在package.json中更新插件版本号,在现有版本号上 + 0.0.1 | ||
| 6. 在example/package.json 中 修改示例 插件的集成版本号。 改为最新的插件版本号。涉及到更改的代码 | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Fix ordered list style and trim trailing spaces
Use “1.” for all items (MD029) and drop trailing spaces (MD009).
-1. 找到需要升级的iOS JPush SDK,替换ios/RCTJPushModule/jpush-ios-x.x.x.xcframework 为需要更新的版本。
-2. 将/ios/RCTJPushModule.xcodeproj/project.pbxproj中关于jpush-ios-x.x.x.xcframework中引用路径的代码,替换为需要更新的版本。
-3. 找到需要升级的Android JPush SDK,替换android/libs/jpush-android-x.x.x.jar 为需要更新的版本。
-4. 在插件中封装需求中需要封装的SDK方法,并在插件示例demo中提供示例调用代码,注意rn插件新增方法还需要再index.js和index.d.ts文件中声明哦。(如果没有需求中没有需要新增的方法,则跳过该步骤)
-5. 在package.json中更新插件版本号,在现有版本号上 + 0.0.1
-6. 在example/package.json 中 修改示例 插件的集成版本号。 改为最新的插件版本号。涉及到更改的代码
+1. 找到需要升级的 iOS JPush SDK,替换 ios/RCTJPushModule/jpush-ios-x.x.x.xcframework 为需要更新的版本。
+1. 将 ios/RCTJPushModule.xcodeproj/project.pbxproj 中关于 jpush-ios-x.x.x.xcframework 的引用路径替换为需要更新的版本。
+1. 找到需要升级的 Android JPush SDK,替换 android/libs/jpush-android-x.x.x.jar 为需要更新的版本。
+1. 在插件中封装需求里的 SDK 新增方法,并在示例工程中提供调用代码;同时在 index.js 和 index.d.ts 中声明。(若无新增方法,跳过)
+1. 在 package.json 中把插件版本号 +0.0.1。
+1. 在 example/package.json 中把示例集成的插件版本号改为最新版本。
@@
- ```
+ ```json
"dependencies": {
...
"jpush-react-native": "^x.x.x",
...
```Also consider moving this file to docs/UPGRADING.md for better discovery.
Also applies to: 32-39
🧰 Tools
🪛 LanguageTool
[uncategorized] ~30-~30: 动词的修饰一般为‘形容词(副词)+地+动词’。您的意思是否是:最新"地"插
Context: ...ample/package.json 中 修改示例 插件的集成版本号。 改为最新的插件版本号。涉及到更改的代码 ``` "dependen...
(wb4)
🤖 Prompt for AI Agents
In cursor.md around lines 25-31 (also applies to 32-39): fix the Markdown lint
issues by making every ordered list item use "1." (MD029) instead of mixed
numbering, and remove all trailing whitespace at the ends of the listed lines
and inside the fenced code block (MD009); update the list markers and trim
trailing spaces in those ranges, validate with markdownlint, and optionally move
the file to docs/UPGRADING.md for better discoverability.
| namespace "com.example" | ||
| defaultConfig { | ||
| applicationId "com.jmessage.sdk" //在此替换你的applicationId | ||
| applicationId "cn.allpublic" | ||
| minSdkVersion rootProject.ext.minSdkVersion |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Namespace vs applicationId mismatch.
namespace "com.example" and applicationId "cn.allpublic" differ. It’s valid, but aligning them simplifies R class/package expectations:
- namespace "com.example"
+ namespace "cn.allpublic"If you intentionally keep them different, ignore.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| namespace "com.example" | |
| defaultConfig { | |
| applicationId "com.jmessage.sdk" //在此替换你的applicationId | |
| applicationId "cn.allpublic" | |
| minSdkVersion rootProject.ext.minSdkVersion | |
| namespace "cn.allpublic" | |
| defaultConfig { | |
| applicationId "cn.allpublic" | |
| minSdkVersion rootProject.ext.minSdkVersion |
🤖 Prompt for AI Agents
In example/android/app/build.gradle around lines 77 to 80, the declared Gradle
namespace ("com.example") does not match the applicationId ("cn.allpublic");
align them to avoid confusion around generated R/package resolution by changing
either the namespace to "cn.allpublic" or the applicationId to "com.example" so
both values match (or explicitly document why they differ if the mismatch is
intentional).
| manifestPlaceholders = [ | ||
| JPUSH_APPKEY: "129c21dc4cb5e6f6de194003", //在此替换你的APPKey | ||
| JPUSH_CHANNEL: "default" //在此替换你的channel | ||
| JPUSH_APPKEY: "32f266ea08c3b3d7a059b378", //在此替换你的APPKey | ||
| JPUSH_CHANNEL: "test" //在此替换你的channel | ||
| ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hardcoded JPUSH_APPKEY committed. Move to secrets.
Do not commit real keys. Read from gradle.properties or CI env and pass via manifestPlaceholders.
- manifestPlaceholders = [
- JPUSH_APPKEY: "32f266ea08c3b3d7a059b378", //在此替换你的APPKey
- JPUSH_CHANNEL: "test" //在此替换你的channel
- ]
+ manifestPlaceholders = [
+ JPUSH_APPKEY: (project.findProperty("JPUSH_APPKEY") ?: ""),
+ JPUSH_CHANNEL: (project.findProperty("JPUSH_CHANNEL") ?: "test")
+ ]Add JPUSH_APPKEY/JPUSH_CHANNEL to local untracked gradle.properties or CI secrets.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| manifestPlaceholders = [ | |
| JPUSH_APPKEY: "129c21dc4cb5e6f6de194003", //在此替换你的APPKey | |
| JPUSH_CHANNEL: "default" //在此替换你的channel | |
| JPUSH_APPKEY: "32f266ea08c3b3d7a059b378", //在此替换你的APPKey | |
| JPUSH_CHANNEL: "test" //在此替换你的channel | |
| ] | |
| manifestPlaceholders = [ | |
| JPUSH_APPKEY: (project.findProperty("JPUSH_APPKEY") ?: ""), | |
| JPUSH_CHANNEL: (project.findProperty("JPUSH_CHANNEL") ?: "test") | |
| ] |
🧰 Tools
🪛 Gitleaks (8.28.0)
[high] 86-86: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
🤖 Prompt for AI Agents
In example/android/app/build.gradle around lines 85 to 88, the JPUSH_APPKEY is
hardcoded into manifestPlaceholders; move the secret to a non-committed
location: read JPUSH_APPKEY and JPUSH_CHANNEL from gradle.properties (project
properties) or CI environment variables and reference those properties in
manifestPlaceholders instead, add a local (untracked) gradle.properties entry
for developers and ensure gradle.properties is gitignored, and configure the CI
to inject the same properties as secrets so the build picks them up without
committing real keys.
| post_install do |installer| | ||
| # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202 | ||
| react_native_post_install( | ||
| installer, | ||
| config[:reactNativePath], | ||
| :mac_catalyst_enabled => false, | ||
| # :ccache_enabled => true | ||
| ) | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove trailing comma in method call
Silences Style/TrailingCommaInArguments.
post_install do |installer|
# https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
react_native_post_install(
installer,
config[:reactNativePath],
:mac_catalyst_enabled => false,
- # :ccache_enabled => true
+ # :ccache_enabled => true
)
endCommittable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 RuboCop (1.81.1)
[convention] 36-36: Avoid comma after the last parameter of a method call.
(Style/TrailingCommaInArguments)
🤖 Prompt for AI Agents
In example/ios/Podfile around lines 31 to 39, the react_native_post_install
method call includes a trailing comma after the last keyword argument
(:mac_catalyst_enabled => false,) which triggers Style/TrailingCommaInArguments;
remove the trailing comma so the final argument has no trailing comma and ensure
formatting remains consistent (i.e., change ":mac_catalyst_enabled => false," to
":mac_catalyst_enabled => false").
| "jcore-react-native": "^2.3.0", | ||
| "jpush-react-native": "^3.2.1", | ||
| "react": "18.2.0", | ||
| "react-native": "0.74.1" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Validate JPush/JCore versions vs RN 0.74
Sanity‑check latest published versions and RN compatibility before locking these.
🏁 Script executed:
#!/bin/bash
npm view jpush-react-native dist-tags versions --json | jq '.[-5:]'
npm view jcore-react-native dist-tags versions --json | jq '.[-5:]'
# Optional: check peer deps if defined
npm view jpush-react-native peerDependenciesLength of output: 182
🌐 Web query:
jpush-react-native 3.2.1 react-native 0.74 compatibility
💡 Result:
Short answer: There’s no official statement that jpush-react-native 3.2.1 is guaranteed compatible with React Native 0.74 — but community experience and Jiguang docs show the React‑Native JPush plugin can work on RN >=0.60 with some manual integration steps (install jcore/jpush packages, Pod install on iOS, Android manifest placeholders, and sometimes manual native init when using Kotlin MainApplication). Test carefully on your app (especially Android new‑architecture / Kotlin MainApplication) and prefer the newer jpush/jcore RN packages or native SDK integration if you hit issues. [1][2][3]
Sources:
- Jiguang (JPush) client plugin / React Native plugin docs. [1]
- React Native 0.74 release notes (notes on breaking changes you should test against). [2]
- Community reports / guides noting manual initialization and fixes needed for RN 0.72+ / Kotlin MainApplication. [3]
🌐 Web query:
jcore-react-native 2.3.0 latest version compatibility
💡 Result:
Short answer — jcore-react-native 2.3.0 compatibility:
- React Native: supports RN 0.77.0 through 0.81.3. [1]
- Native SDKs: iOS SDK upgraded to 3.6.0 and Android SDK to 4.5.0. [1]
- Platform minimums: Android minSdkVersion = 24 (documentation fix noted). (iOS minimum was raised to ~15.1 in earlier 2.1.0 release). [1][3]
- Note: npm shows a newer patch release (2.3.1) available. If you need the absolute latest, consider using 2.3.1. [2]
Sources:
[1] jcore-react-native release notes (2.3.0).
[2] npm jcore-react-native package page (version 2.3.1).
[3] jcore-react-native release notes (2.1.0 iOS / Android minimums).
Downgrade jcore-react-native or upgrade React Native
jcore-react-native 2.3.0 supports RN 0.77.0 through 0.81.3—not 0.74.1. This creates a version mismatch. Either use an older jcore-react-native release compatible with RN 0.74 or upgrade React Native to 0.77+. Additionally, jpush-react-native 3.2.1 has no official RN 0.74 compatibility statement and may need manual integration steps. Test thoroughly before merging.
🤖 Prompt for AI Agents
In example/package.json around lines 13 to 16, there's a version mismatch:
[email protected] requires RN >=0.77 while the project uses
[email protected]; fix by either downgrading jcore-react-native to a release
that explicitly supports RN 0.74 (replace the dependency with that older
version) or upgrade react-native to >=0.77.0 (update package.json react-native
version, run yarn/npm install and ios/Android platform installs like pod
install). Also review [email protected] for RN 0.74 compatibility and be
prepared to perform any manual integration steps or choose a compatible
jpush/jcore combo, then run full iOS/Android builds and automated/manual tests
before merging.
| @@ -0,0 +1,79 @@ | |||
| This is a new [**React Native**](https://reactnative.dev) project, bootstrapped using [`@react-native-community/cli`](https://github.com/react-native-community/cli). | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Add h1 heading at the top for proper document structure.
Markdown files should start with a level-1 heading. Consider adding:
# React Native Example AppBased on coding guidelines
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
1-1: First line in a file should be a top-level heading
(MD041, first-line-heading, first-line-h1)
🤖 Prompt for AI Agents
In example/README.md around lines 1 to 1, the file lacks a top-level heading;
add a level-1 heading at the very top of the file such as "React Native Example
App" (i.e., a single line with "# React Native Example App"), then add a blank
line before the existing sentence to ensure proper Markdown document structure
and readability.
|
|
||
| # Getting Started | ||
|
|
||
| >**Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till "Creating a new application" step, before proceeding. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Use "until" instead of "till" for formal tone.
Replace "till" with "until" for clearer, more professional documentation.
Apply this diff:
->**Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till "Creating a new application" step, before proceeding.
+>**Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions until "Creating a new application" step, before proceeding.Based on coding guidelines
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| >**Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till "Creating a new application" step, before proceeding. | |
| >**Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions until "Creating a new application" step, before proceeding. |
🧰 Tools
🪛 LanguageTool
[style] ~5-~5: Consider using the more formal “until”.
Context: ...ev/docs/environment-setup) instructions till "Creating a new application" step, befo...
(TILL)
🤖 Prompt for AI Agents
In example/README.md around line 5, the word "till" should be replaced with
"until" to use a more formal tone; edit the sentence ">**Note**: Make sure you
have completed the [React Native - Environment
Setup](https://reactnative.dev/docs/environment-setup) instructions till
"Creating a new application" step, before proceeding." by substituting "till"
with "until" so it reads "...instructions until "Creating a new application"
step, before proceeding."
| @@ -0,0 +1 @@ | |||
| npm publish No newline at end of file | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarify purpose or remove this file.
A file named rm.txt containing only "npm publish" looks like it was accidentally committed. If it's a release helper script, rename it to something clearer (e.g., publish.sh) and add it to .gitignore. If it's not needed, remove it.
🤖 Prompt for AI Agents
In rm.txt around lines 1 to 1, the file contains only "npm publish" which is
unclear and likely accidental; either remove the file if not needed, or rename
it to a clear, descriptive script name (e.g., publish.sh) and add a proper
shebang and executable permissions, commit the renamed file, and add the new
filename to .gitignore if it should not be tracked; if keeping a tracked helper,
move it into a scripts/ directory and update README/CI docs to explain its
purpose.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review continued from previous batch...
| <!-- Optional. Required for location feature --> | ||
| <!-- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> | ||
| <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> | ||
| <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix the comment block; it currently comments out unrelated permissions.
Close the comment after the 3 location lines and remove the stray trailing -->.
- <!-- Optional. Required for location feature -->
- <!-- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
- <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
+ <!-- Optional. Required for location feature
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
+ -->
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> -->Also applies to: 31-32
🤖 Prompt for AI Agents
In android/src/main/AndroidManifest.xml around lines 20-23 (and similarly lines
31-32), the comment block currently opens before the three location permission
lines but fails to close correctly, leaving a stray "-->" that ends up
commenting out unrelated permissions; fix it by moving the closing comment tag
(--> ) immediately after the three location <uses-permission ... /> lines so
only those three are commented, and remove any stray or duplicate comment
markers so surrounding permissions remain active.
| <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/> | ||
| <uses-permission android:name="android.permission.GET_TASKS" /> | ||
| <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> | ||
| <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> | ||
| <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> | ||
| <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove non‑Play‑compliant or obsolete permissions.
QUERY_ALL_PACKAGES (API 30+) needs strong Play justification; GET_TASKS and MOUNT_UNMOUNT_FILESYSTEMS are legacy/privileged.
- <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
- <uses-permission android:name="android.permission.GET_TASKS" />
...
- <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />🤖 Prompt for AI Agents
In android/src/main/AndroidManifest.xml around lines 25 to 30 the manifest
declares QUERY_ALL_PACKAGES, GET_TASKS and MOUNT_UNMOUNT_FILESYSTEMS which are
non‑compliant or obsolete; remove these three permissions from the manifest and
keep only needed runtime permissions (e.g., ACCESS_WIFI_STATE,
READ/WRITE_EXTERNAL_STORAGE if still required and scoped to API levels), or if
QUERY_ALL_PACKAGES is absolutely required, remove it here and instead implement
a documented Play-allowed alternative with a proper Play Console justification
and runtime-scoped package visibility via <queries>; also delete GET_TASKS and
MOUNT_UNMOUNT_FILESYSTEMS since they are legacy/privileged and replace any
functionality with modern APIs (UsageStatsManager, Storage Access Framework, or
scoped storage) as appropriate.
| android:exported="true" | ||
| android:theme="@style/MyDialogStyle" > | ||
| <intent-filter> | ||
| <category android:name="android.intent.category.DEFAULT" /> | ||
| <action android:name="cn.jpush.android.ui.PopWinActivity" /> | ||
| <category android:name="${applicationId}" /> | ||
| </intent-filter> | ||
| </activity> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Reassess exporting PopWinActivity.
If external apps shouldn’t launch it, drop the intent-filter or add tighter guards. At minimum, keep only DEFAULT + ${applicationId} category; avoid custom action if not required.
🤖 Prompt for AI Agents
In android/src/main/AndroidManifest.xml around lines 37 to 44 the PopWinActivity
is exported and defines an intent-filter with a custom action which allows
external apps to launch it; either remove the intent-filter entirely if external
launch is not desired, or tighten it by deleting the custom action line and
keeping only the DEFAULT and ${applicationId} category; alternatively, if no
implicit intents are needed set android:exported="false" on the activity to
prevent external apps from launching it.
| <action android:name="cn.jpush.android.intent.RECEIVER_MESSAGE" /> | ||
| <category android:name="${applicationId}" /> | ||
| </intent-filter> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Receiver action name looks wrong; likely breaks message delivery.
Use cn.jpush.android.intent.RECEIVE_MESSAGE (not RECEIVER_MESSAGE).
Apply this diff:
- <action android:name="cn.jpush.android.intent.RECEIVER_MESSAGE" />
+ <action android:name="cn.jpush.android.intent.RECEIVE_MESSAGE" />📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <action android:name="cn.jpush.android.intent.RECEIVER_MESSAGE" /> | |
| <category android:name="${applicationId}" /> | |
| </intent-filter> | |
| <action android:name="cn.jpush.android.intent.RECEIVE_MESSAGE" /> | |
| <category android:name="${applicationId}" /> | |
| </intent-filter> |
🤖 Prompt for AI Agents
In android/src/main/AndroidManifest.xml around lines 75 to 77, the JPush
receiver action is incorrectly specified as
"cn.jpush.android.intent.RECEIVER_MESSAGE"; change it to the correct action name
"cn.jpush.android.intent.RECEIVE_MESSAGE". Update the <action android:name=.../>
entry to use the corrected constant so the intent-filter matches JPush messages
and message delivery works as expected.
| public void setChannelAndSound(ReadableMap readableMap) { | ||
| if (readableMap == null) { | ||
| JLogger.w(JConstants.PARAMS_NULL); | ||
| return; | ||
| } | ||
| String channel = readableMap.getString(JConstants.CHANNEL); | ||
| String sound = readableMap.getString(JConstants.SOUND); | ||
| String channelId = readableMap.getString(JConstants.CHANNELID); | ||
| try { | ||
| NotificationManager manager= (NotificationManager) reactContext.getSystemService("notification"); | ||
| if(Build.VERSION.SDK_INT<26){ | ||
| return; | ||
| } | ||
| if(TextUtils.isEmpty(channel)||TextUtils.isEmpty(channelId)){ | ||
| return; | ||
| } | ||
| NotificationChannel channel1=new NotificationChannel(channelId,channel, NotificationManager.IMPORTANCE_HIGH); | ||
| if(!TextUtils.isEmpty(sound)){ | ||
| channel1.setSound(Uri.parse("android.resource://"+reactContext.getPackageName()+"/raw/"+sound),null); | ||
| } | ||
| manager.createNotificationChannel(channel1); | ||
| JPushInterface.setChannel(reactContext,channel); | ||
| }catch (Throwable throwable){ | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Harden setChannelAndSound: key checks, proper service constant, audio attributes, and logging.
Current code can throw before try, swallows all errors, and sets sound without AudioAttributes.
- public void setChannelAndSound(ReadableMap readableMap) {
- if (readableMap == null) {
- JLogger.w(JConstants.PARAMS_NULL);
- return;
- }
- String channel = readableMap.getString(JConstants.CHANNEL);
- String sound = readableMap.getString(JConstants.SOUND);
- String channelId = readableMap.getString(JConstants.CHANNELID);
- try {
- NotificationManager manager= (NotificationManager) reactContext.getSystemService("notification");
- if(Build.VERSION.SDK_INT<26){
- return;
- }
- if(TextUtils.isEmpty(channel)||TextUtils.isEmpty(channelId)){
- return;
- }
- NotificationChannel channel1=new NotificationChannel(channelId,channel, NotificationManager.IMPORTANCE_HIGH);
- if(!TextUtils.isEmpty(sound)){
- channel1.setSound(Uri.parse("android.resource://"+reactContext.getPackageName()+"/raw/"+sound),null);
- }
- manager.createNotificationChannel(channel1);
- JPushInterface.setChannel(reactContext,channel);
- }catch (Throwable throwable){
- }
- }
+ public void setChannelAndSound(ReadableMap readableMap) {
+ if (readableMap == null) {
+ JLogger.w(JConstants.PARAMS_NULL);
+ return;
+ }
+ try {
+ String channel = readableMap.hasKey(JConstants.CHANNEL) ? readableMap.getString(JConstants.CHANNEL) : null;
+ String sound = readableMap.hasKey(JConstants.SOUND) ? readableMap.getString(JConstants.SOUND) : null;
+ String channelId = readableMap.hasKey(JConstants.CHANNELID) ? readableMap.getString(JConstants.CHANNELID) : null;
+ if (TextUtils.isEmpty(channel)) {
+ JLogger.w(JConstants.PARAMS_ILLEGAL);
+ return;
+ }
+ if (Build.VERSION.SDK_INT >= 26) {
+ if (TextUtils.isEmpty(channelId)) {
+ JLogger.w("channelId is required on Android O+");
+ return;
+ }
+ NotificationManager manager = (NotificationManager) reactContext.getSystemService(android.content.Context.NOTIFICATION_SERVICE);
+ if (manager == null) {
+ JLogger.w("NotificationManager is null");
+ return;
+ }
+ NotificationChannel ch = new NotificationChannel(channelId, channel, NotificationManager.IMPORTANCE_HIGH);
+ if (!TextUtils.isEmpty(sound)) {
+ Uri uri = Uri.parse("android.resource://" + reactContext.getPackageName() + "/raw/" + sound);
+ android.media.AudioAttributes attrs = new android.media.AudioAttributes.Builder()
+ .setUsage(android.media.AudioAttributes.USAGE_NOTIFICATION)
+ .setContentType(android.media.AudioAttributes.CONTENT_TYPE_SONIFICATION)
+ .build();
+ ch.setSound(uri, attrs);
+ }
+ manager.createNotificationChannel(ch);
+ }
+ // Still set logical channel for JPush
+ JPushInterface.setChannel(reactContext, channel);
+ } catch (Exception e) {
+ JLogger.w("setChannelAndSound failed: " + e.getMessage());
+ }
+ }🤖 Prompt for AI Agents
In android/src/main/java/cn/jiguang/plugins/push/JPushModule.java around lines
106-130, move the reading/validation of readableMap keys into the try block (or
check hasKey/isNull before calling getString) so getString doesn't throw outside
the catch; use Context.NOTIFICATION_SERVICE instead of the literal
"notification" when calling getSystemService; only proceed with
channel/channelId logic after confirming SDK >= 26 and that channel/channelId
are non-empty; when setting a custom sound build proper AudioAttributes and call
channel.setSound(uri, audioAttributes) instead of passing null; log any caught
Throwable with JLogger.e (include the throwable) rather than swallowing it; and
call JPushInterface.setChannel only after the NotificationChannel is
successfully created.
| RCT_EXPORT_METHOD(isNotificationEnabled:(RCTResponseSenderBlock) callback) { | ||
| [JPUSHService requestNotificationAuthorization:^(JPAuthorizationStatus status) { | ||
| if (status <= JPAuthorizationStatusDenied) { | ||
| callback(@[@(NO)]); | ||
| }else { | ||
| callback(@[@(YES)]); | ||
| } | ||
| }]; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
isNotificationEnabled() prompts the user.
requestNotificationAuthorization may show a permission prompt; this is not a pure “check”. Consider a read-only status API or rename to requestNotificationAuthorization.
🤖 Prompt for AI Agents
In ios/RCTJPushModule/RCTJPushModule.m around lines 176 to 184, the exported
isNotificationEnabled method currently calls requestNotificationAuthorization
which can present a system permission prompt; change it to a read-only check or
rename the exported method to reflect that it requests authorization. To make it
a pure check, replace the call with a non-prompting API (e.g.,
JPUSHService.authorizationStatus or UNUserNotificationCenter's
getNotificationSettings: and map the authorization status to YES/NO) so the
method only reads state; if you intend to keep the prompt behavior instead,
rename the JS-facing method to requestNotificationAuthorization and keep the
existing implementation so callers are aware it may show UI.
| - (void)sendPropertiesEvent:(NSDictionary *)data | ||
| { | ||
| [self.bridge enqueueJSCall:@"RCTDeviceEventEmitter" | ||
| method:@"emit" | ||
| args:@[PROPERTIES_EVENT, data] | ||
| completion:NULL]; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Properties events are not subscribed; and wrong emitter used elsewhere.
- supportedEvents misses PROPERTIES_EVENT, so events are dropped.
- deleteProperties/cleanProperties emit TagAlias instead of Properties.
// supportedEvents
- return @[CONNECT_EVENT,NOTIFICATION_EVENT,CUSTOM_MESSAGE_EVENT,LOCAL_NOTIFICATION_EVENT,TAG_ALIAS_EVENT,MOBILE_NUMBER_EVENT,INAPP_MESSAGE_EVENT];
+ return @[CONNECT_EVENT,NOTIFICATION_EVENT,CUSTOM_MESSAGE_EVENT,LOCAL_NOTIFICATION_EVENT,TAG_ALIAS_EVENT,MOBILE_NUMBER_EVENT,INAPP_MESSAGE_EVENT,PROPERTIES_EVENT];
// deleteProperties completion emitter
- [self sendTagAliasEvent:data];
+ [self sendPropertiesEvent:data];
// cleanProperties completion emitter
- [self sendTagAliasEvent:data];
+ [self sendPropertiesEvent:data];Also applies to: 516-517
🤖 Prompt for AI Agents
In ios/RCTJPushModule/RCTJPushModule.m around lines 410-416 and also lines
~516-517, supportedEvents is missing PROPERTIES_EVENT so property events are
dropped, and deleteProperties/cleanProperties are emitting the TagAlias event
instead of Properties; add PROPERTIES_EVENT to the supportedEvents array (ensure
the PROPERTIES_EVENT constant is defined/imported) and update the emit calls in
deleteProperties and cleanProperties to use PROPERTIES_EVENT (replace the
incorrect TagAlias emitter usage), leaving sendPropertiesEvent as the emitter
caller.
| if (@available(iOS 15.0, *)) { | ||
| content.interruptionLevel = 1; | ||
| } else { | ||
| // Fallback on earlier versions | ||
| } | ||
| if(params[EXTRAS]){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don’t hard‑code interruptionLevel.
Make it configurable (param) or leave unset to respect system defaults.
🤖 Prompt for AI Agents
In ios/RCTJPushModule/RCTJPushModule.m around lines 446 to 451, the code
currently hard-sets content.interruptionLevel = 1 for iOS 15+; instead, make
interruptionLevel configurable by checking a provided param (e.g.,
params[@"interruptionLevel"]) and only set content.interruptionLevel when that
param exists and is a valid UNNotificationInterruptionLevel value (or map an
integer/string to the enum), otherwise leave interruptionLevel unset so the
system default applies; validate the param type/range and guard with the
@available(iOS 15.0, *) check before assignment.
| - (NSDictionary *)convertInappMsg:(JPushInAppMessage *)inAppMessage isShow:(BOOL)isShow{ | ||
| NSDictionary *result = @{ | ||
| @"mesageId": inAppMessage.mesageId ?: @"", // 消息id | ||
| @"title": inAppMessage.title ?:@"", // 标题 | ||
| @"content": inAppMessage.content ?: @"", // 内容 | ||
| @"target": inAppMessage.target ?: @[], // 目标页面 | ||
| @"clickAction": inAppMessage.clickAction ?: @"", // 跳转地址 | ||
| @"extras": inAppMessage.extras ?: @{}, // 附加字段 | ||
| INAPP_MESSAGE_EVENT_TYPE: isShow ? INAPP_MESSAGE_SHOW : INAPP_MESSAGE_CLICK // 类型 | ||
| }; | ||
| return result; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix typos and key names in in-app message payload.
Use messageId (not mesageId). Keep keys consistent with Android.
- NSDictionary *result = @{
- @"mesageId": inAppMessage.mesageId ?: @"", // 消息id
- @"title": inAppMessage.title ?:@"", // 标题
+ NSDictionary *result = @{
+ @"messageId": inAppMessage.messageId ?: @"", // 消息id
+ @"title": inAppMessage.title ?: @"", // 标题
@"content": inAppMessage.content ?: @"", // 内容
@"target": inAppMessage.target ?: @[], // 目标页面
@"clickAction": inAppMessage.clickAction ?: @"", // 跳转地址
@"extras": inAppMessage.extras ?: @{}, // 附加字段
INAPP_MESSAGE_EVENT_TYPE: isShow ? INAPP_MESSAGE_SHOW : INAPP_MESSAGE_CLICK // 类型
};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - (NSDictionary *)convertInappMsg:(JPushInAppMessage *)inAppMessage isShow:(BOOL)isShow{ | |
| NSDictionary *result = @{ | |
| @"mesageId": inAppMessage.mesageId ?: @"", // 消息id | |
| @"title": inAppMessage.title ?:@"", // 标题 | |
| @"content": inAppMessage.content ?: @"", // 内容 | |
| @"target": inAppMessage.target ?: @[], // 目标页面 | |
| @"clickAction": inAppMessage.clickAction ?: @"", // 跳转地址 | |
| @"extras": inAppMessage.extras ?: @{}, // 附加字段 | |
| INAPP_MESSAGE_EVENT_TYPE: isShow ? INAPP_MESSAGE_SHOW : INAPP_MESSAGE_CLICK // 类型 | |
| }; | |
| return result; | |
| } | |
| - (NSDictionary *)convertInappMsg:(JPushInAppMessage *)inAppMessage isShow:(BOOL)isShow{ | |
| NSDictionary *result = @{ | |
| @"messageId": inAppMessage.messageId ?: @"", // 消息id | |
| @"title": inAppMessage.title ?: @"", // 标题 | |
| @"content": inAppMessage.content ?: @"", // 内容 | |
| @"target": inAppMessage.target ?: @[], // 目标页面 | |
| @"clickAction": inAppMessage.clickAction ?: @"", // 跳转地址 | |
| @"extras": inAppMessage.extras ?: @{}, // 附加字段 | |
| INAPP_MESSAGE_EVENT_TYPE: isShow ? INAPP_MESSAGE_SHOW : INAPP_MESSAGE_CLICK // 类型 | |
| }; | |
| return result; | |
| } |
🤖 Prompt for AI Agents
In ios/RCTJPushModule/RCTJPushModule.m around lines 708 to 719, the in-app
message payload has a typo and inconsistent key naming: replace the @"mesageId"
key with @"messageId" to match Android and fix the typo, keep the rest of the
dictionary keys the same and ensure the value uses inAppMessage.messageId ?: @""
so the payload is consistent across platforms.
|
|
||
| s.name = "JPush" | ||
| s.name = "JPushRN" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Remove extra empty line.
RuboCop flagged an extra empty line at the block body beginning.
As per static analysis hints.
Apply this diff:
Pod::Spec.new do |s|
-
s.name = "JPushRN"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| s.name = "JPush" | |
| s.name = "JPushRN" | |
| Pod::Spec.new do |s| | |
| s.name = "JPushRN" |
🧰 Tools
🪛 RuboCop (1.81.1)
[convention] 5-6: Extra empty line detected at block body beginning.
(Layout/EmptyLinesAroundBlockBody)
🤖 Prompt for AI Agents
In JPushRN.podspec around lines 5 to 6, remove the extra blank line at the start
of the block body so the file has no empty line between the opening of the
podspec and the s.name assignment (i.e., delete the empty line so s.name =
"JPushRN" immediately follows the block start).
Summary by CodeRabbit
Release Notes
New Features
Bug Fixes
Chores