Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
107 commits
Select commit Hold shift + click to select a range
3cd3bd8
fix addCustomMessageListener 方法报错问题
huangshuni Aug 30, 2022
7d95852
Merge pull request #885 from huangshuni/master
huangshuni Aug 30, 2022
d3e465b
更新Jpush4.8.1,新增对外API:设置用户属性。对外版本号293,
LcTerry Aug 30, 2022
b833fe9
Merge pull request #886 from LcTerry/master
LcTerry Aug 30, 2022
a218bf4
更新iOS Jpush4.8.1,新增对外API:设置用户属性。对外版本号294
huangshuni Sep 9, 2022
006b0c5
Merge pull request #888 from huangshuni/master
huangshuni Sep 9, 2022
1b3c479
解决iOS 杀死状态点击通知进入app没有回调通知的问题
huangshuni Oct 10, 2022
703e4d8
Merge pull request #893 from huangshuni/master
huangshuni Oct 10, 2022
34b8198
更新Jpush4.8.3,对外版本号295,
LcTerry Oct 11, 2022
8bfe4e6
更新清单文件配置+版本296
LcTerry Oct 11, 2022
927f068
更新清单文件配置+版本297
LcTerry Oct 12, 2022
d094cf9
Merge remote-tracking branch 'main/master'
LcTerry Jan 12, 2023
99fcc32
Merge pull request #906 from LcTerry/master
LcTerry Apr 6, 2023
00af791
【iOS】解决没有初始化,但是会请求通知权限弹窗的问题
huangshuni Apr 7, 2023
5cc4a9e
Merge pull request #908 from huangshuni/master
huangshuni Apr 7, 2023
5a743dc
升级iOS jpush SDK到4.9.0, 更新插件版本号为2.9.8
huangshuni Apr 7, 2023
3c3235d
Merge pull request #909 from huangshuni/master
huangshuni Apr 7, 2023
bfa70ea
更新JPush 500
LcTerry Apr 11, 2023
6110895
Merge pull request #910 from LcTerry/master
LcTerry Apr 11, 2023
89ed69d
【iOS】更新到jpush5.0.0
huangshuni Apr 11, 2023
462a1b4
Merge pull request #911 from huangshuni/master
huangshuni Apr 11, 2023
3498c6a
【ios】fix
huangshuni Apr 11, 2023
d44d379
Merge pull request #912 from huangshuni/master
huangshuni Apr 11, 2023
05b0228
更新JPush 500:适配新回调
LcTerry Apr 11, 2023
5feb793
Merge pull request #913 from LcTerry/master
LcTerry Apr 11, 2023
9738417
更新demo的jcore版本,fixdemo警告
huangshuni Apr 14, 2023
c085c9f
Merge pull request #914 from huangshuni/master
huangshuni Apr 14, 2023
399d6a6
更新JPush 504,对外版本号2.9.9
LcTerry Jul 3, 2023
165e11e
Merge pull request #919 from LcTerry/master
LcTerry Jul 3, 2023
db35edd
开放:setChannelAndSound
LcTerry Jul 25, 2023
8fa1908
更新版本号3.0.0
LcTerry Jul 25, 2023
5a49236
Merge pull request #920 from LcTerry/master
LcTerry Jul 25, 2023
ee35cb9
开放本地通知定时展示字段
LcTerry Aug 4, 2023
23154c9
Merge remote-tracking branch 'main/master'
LcTerry Aug 4, 2023
16d4ab9
Merge pull request #921 from LcTerry/master
LcTerry Aug 4, 2023
f6fba6e
ios 开放本地通知定时展示字段
huangshuni Aug 4, 2023
488cb13
Merge pull request #922 from huangshuni/master
huangshuni Aug 4, 2023
fbb68bc
更新版本号3.0.1
LcTerry Aug 7, 2023
1a95b32
Merge pull request #923 from LcTerry/master
LcTerry Aug 7, 2023
aea8e8a
ios 开放本地通知定时展示字段fix,修改版本号为3.0.2
huangshuni Aug 7, 2023
cb1aa1e
Merge pull request #924 from huangshuni/master
huangshuni Aug 7, 2023
bf4590f
iOS新增获取通知权限开关的接口,修改版本号为3.0.3
huangshuni Aug 15, 2023
ac83f6b
Merge pull request #925 from huangshuni/master
huangshuni Aug 15, 2023
84f5f63
修改init参数channel名
huangshuni Sep 11, 2023
f22de5e
Merge pull request #930 from huangshuni/master
huangshuni Sep 11, 2023
cfcdd51
更新版本号3.0.4 + 暴露CommandEvent 回调
LcTerry Sep 13, 2023
66fd0ce
Merge pull request #931 from LcTerry/master
LcTerry Sep 13, 2023
b12deec
更新JPush 520
LcTerry Sep 21, 2023
6caa607
Merge pull request #933 from LcTerry/master
LcTerry Sep 21, 2023
b7ecc60
iOS 更新SDK为520
huangshuni Sep 22, 2023
83b3e34
Merge pull request #934 from huangshuni/master
huangshuni Sep 22, 2023
77963bb
更新版本号3.0.5
LcTerry Sep 25, 2023
387c14b
iOS 更新SDK为530, 版本号更新为3.0.5
huangshuni Apr 25, 2024
e819315
Merge pull request #941 from huangshuni/master
huangshuni Apr 25, 2024
7df3067
修改清单文件配置
LcTerry Apr 25, 2024
b394de8
Merge pull request #942 from LcTerry/master
LcTerry Apr 25, 2024
ebb2996
更新版本号3.0.6
LcTerry Apr 25, 2024
689f6b0
Merge pull request #943 from LcTerry/master
LcTerry Apr 25, 2024
9d43325
更新版本号为3.0.7
huangshuni Apr 25, 2024
fddbb5a
Merge pull request #944 from huangshuni/master
huangshuni Apr 25, 2024
4f64d47
修改版本号为3.0.8
huangshuni Apr 25, 2024
316e442
Merge pull request #945 from huangshuni/master
huangshuni Apr 25, 2024
4c24ab0
更新版适配rn 0.74
May 30, 2024
9f4be94
更新版 版本号3.0.7
May 30, 2024
133ef7f
Merge remote-tracking branch 'main/master'
May 30, 2024
482c9f7
Merge pull request #947 from LcTerry/master
LcTerry May 31, 2024
54f08c2
补充iOS appdelegate.m 中的代码
huangshuni Jun 24, 2024
ec29ce7
Merge pull request #949 from huangshuni/master
huangshuni Jun 24, 2024
0a3f279
更新版JPush 540 版本号3.1.0
Jul 4, 2024
4ccc1c7
ios demo更新
huangshuni Jul 9, 2024
c1d9c30
demo更新
huangshuni Jul 9, 2024
68ae328
修改安卓demo
huangshuni Jul 9, 2024
9273903
Merge pull request #950 from huangshuni/master
huangshuni Jul 9, 2024
ef98578
Merge remote-tracking branch 'main/master'
Jul 9, 2024
9a32604
Merge pull request #951 from LcTerry/master
LcTerry Jul 9, 2024
5d71b6a
更新安卓demo
huangshuni Jul 9, 2024
355ac46
Merge pull request #952 from huangshuni/master
huangshuni Jul 9, 2024
cd5ff64
修复Android studio run 报错
Jul 10, 2024
36a8f77
删除,否则界面新加功能后,显示还是老的
Jul 10, 2024
7f6318f
ios SDK更新到5.4.0版本
huangshuni Sep 30, 2024
cd028ed
Merge pull request #961 from huangshuni/master
huangshuni Sep 30, 2024
cf0bc28
更新JPush 550+版本号3.1.1
Oct 8, 2024
47c8764
更新demo使用插件版本
huangshuni Oct 12, 2024
7f518ab
iOS 修复jpush的代理设置问题。
huangshuni Nov 19, 2024
89c54ad
Merge pull request #965 from huangshuni/master
huangshuni Nov 19, 2024
c9862a3
更新版本号为3.1.2
huangshuni Nov 19, 2024
e4d4c00
Merge pull request #966 from huangshuni/master
huangshuni Nov 19, 2024
daff0ba
iOS 更新到jpush550
huangshuni Jan 16, 2025
285e490
更新JPush 560+版本号3.1.2
LcTerry Feb 11, 2025
b1752a2
ts中新增addCommandEventListener +版本号3.1.4
LcTerry Mar 18, 2025
eba0a7f
ios 更新到jpush560, JPush.podspec 改为JPushRN.podspec。
huangshuni Apr 22, 2025
a0ddaf2
版本号改为3.1.5
huangshuni Apr 22, 2025
45c3731
更新demo
huangshuni Apr 22, 2025
99c2d27
android更新JPush 570+版本号3.1.6+新增setDataInsightsEnable接口
huangshuni May 8, 2025
3e94519
修复 iOS bool 问题
huangshuni Jun 13, 2025
11c4b92
fix 安卓点击通知不回调问题,更新版本号为3.1.8
huangshuni Jun 20, 2025
e03b9a0
新增cursor快速更新模版文档
huangshuni Jul 7, 2025
9f5c2fb
本地通知添加category、priority、builderName属性
Jul 8, 2025
ce7a937
本地通知添加category、priority、builderName属性
Jul 8, 2025
62fef2d
本地通知添加category、priority、builderName属性
Jul 9, 2025
ccc8fef
本地通知添加category、priority、builderName属性
Jul 9, 2025
a4fb1fa
本地通知添加category、priority、builderName属性
Jul 9, 2025
756b89a
3.2.0:android 5.8.0 ios 5.7.0
Jul 22, 2025
376651e
添加iOS-Swift代码示例
huangshuni Sep 23, 2025
8d00e18
3.2.1:android 5.9.0 ios 5.9.0
huangshuni Oct 21, 2025
3e28355
Merge branch 'jpush/master'
ByteZhang1024 Oct 22, 2025
33eca9e
chore: update jpush
ByteZhang1024 Oct 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
example/
cursor.md
4 changes: 2 additions & 2 deletions JPush.podspec → JPushRN.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pjson = JSON.parse(File.read('package.json'))

Pod::Spec.new do |s|

s.name = "JPush"
s.name = "JPushRN"
Comment on lines 5 to +6
Copy link

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.

Suggested change
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).

s.version = pjson["version"]
s.homepage = pjson["homepage"]
s.summary = pjson["description"]
Expand All @@ -18,6 +18,6 @@ Pod::Spec.new do |s|
s.frameworks = 'UIKit','CFNetwork','CoreFoundation','CoreTelephony','SystemConfiguration','CoreGraphics','Foundation','Security'
s.weak_frameworks = 'UserNotifications'
s.libraries = 'z','resolv'
s.vendored_libraries = "ios/RCTJPushModule/*.a"
s.vendored_frameworks = "ios/RCTJPushModule/*.xcframework"
s.dependency 'React'
end
9 changes: 6 additions & 3 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ def safeExtGet(prop, fallback) {
}

android {
compileSdkVersion safeExtGet('compileSdkVersion', 27)
compileSdkVersion safeExtGet('compileSdkVersion', 34)

namespace 'cn.jiguang.plugins.push'

defaultConfig {
minSdkVersion safeExtGet('minSdkVersion', 16)
targetSdkVersion safeExtGet('targetSdkVersion', 27)
minSdkVersion safeExtGet('minSdkVersion', 23)
targetSdkVersion safeExtGet('targetSdkVersion', 34)
versionCode 1
versionName "1.0"

Expand Down
Binary file removed android/libs/jpush-android-4.8.0.jar
Binary file not shown.
Binary file added android/libs/jpush-android-5.9.0.jar
Binary file not shown.
60 changes: 37 additions & 23 deletions android/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,38 +1,47 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.jiguang.plugins.push">
>

<permission
android:name="${applicationId}.permission.JPUSH_MESSAGE"
android:protectionLevel="signature" />

<!-- Required -->
<uses-permission android:name="${applicationId}.permission.JPUSH_MESSAGE" />
<uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<!--华为角标-->
<uses-permission android:name="com.huawei.android.launcher.permission.CHANGE_BADGE"/>
<!--vivo 角标-->
<uses-permission android:name="com.vivo.notification.permission.BADGE_ICON" />
<!--honor 角标-->
<uses-permission android:name="com.hihonor.android.launcher.permission.CHANGE_BADGE" />
<!--小米 推送必须-->
<uses-permission android:name="android.permission.VIBRATE" />
<!-- 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" />
Comment on lines +20 to +23
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

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.READ_PHONE_STATE" />
<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" />
Comment on lines +25 to 30
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

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.

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

<!-- Optional. Required for location feature -->
<!-- <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/> -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> -->

<application>
<activity
android:name="cn.jpush.android.ui.PopWinActivity"
android:exported="false"
android:theme="@style/MyDialogStyle" />
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>
Comment on lines +37 to +44
Copy link

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.


<activity
android:name="cn.jpush.android.ui.PushActivity"
Expand All @@ -50,7 +59,7 @@
<activity
android:name="cn.jpush.android.service.JNotifyActivity"
android:exported="true"
android:taskAffinity="jpush.custom"
android:taskAffinity=""
android:theme="@style/JPushTheme">
<intent-filter>
<action android:name="cn.jpush.android.intent.JNotifyActivity" />
Expand All @@ -63,7 +72,7 @@
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="cn.jpush.android.intent.RECEIVE_MESSAGE" />
<action android:name="cn.jpush.android.intent.RECEIVER_MESSAGE" />
<category android:name="${applicationId}" />
</intent-filter>
Comment on lines +75 to 77
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

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.

Suggested change
<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.

</receiver>
Expand All @@ -83,7 +92,7 @@
<activity
android:name="cn.android.service.JTransitActivity"
android:exported="true"
android:taskAffinity="jpush.custom"
android:taskAffinity=""
android:theme="@style/JPushTheme" >
<intent-filter>
<action android:name="cn.android.service.JTransitActivity" />
Expand All @@ -95,13 +104,18 @@
android:enabled="true"
android:exported="true"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:taskAffinity="jpush.custom">
android:taskAffinity="">
<intent-filter>
<action android:name="cn.jpush.android.intent.DActivity"/>
<category android:name="${applicationId}" />
</intent-filter>
</activity>

<provider
android:name="cn.jpush.android.service.InitProvider"
android:authorities="${applicationId}.jiguang.InitProvider"
android:exported="false"
android:readPermission="${applicationId}.permission.JPUSH_MESSAGE"
android:writePermission="${applicationId}.permission.JPUSH_MESSAGE" />
</application>

</manifest>
183 changes: 182 additions & 1 deletion android/src/main/java/cn/jiguang/plugins/push/JPushModule.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@

package cn.jiguang.plugins.push;

import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.net.Uri;
import android.os.Build;
import android.app.Activity;
import android.app.Application;
import android.os.Bundle;
Expand All @@ -14,19 +17,23 @@
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableNativeMap;
import com.facebook.react.bridge.WritableMap;

import org.json.JSONObject;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.lang.*;

import cn.jiguang.plugins.push.common.JConstants;
import cn.jiguang.plugins.push.common.JLogger;
import cn.jiguang.plugins.push.helper.JPushHelper;
import cn.jiguang.plugins.push.receiver.JPushBroadcastReceiver;
import cn.jpush.android.api.BasicPushNotificationBuilder;
import cn.jpush.android.api.JPushInterface;
import cn.jpush.android.data.JPushCollectControl;
import cn.jpush.android.data.JPushLocalNotification;

public class JPushModule extends ReactContextBaseJavaModule {
Expand Down Expand Up @@ -59,6 +66,7 @@ public void init() {
JPushHelper.sendEvent(JConstants.NOTIFICATION_EVENT, writableMap);
JPushBroadcastReceiver.NOTIFICATION_BUNDLE = null;
}
JPushInterface.setNotificationCallBackEnable(reactContext,true);
}

@ReactMethod
Expand Down Expand Up @@ -95,6 +103,92 @@ public void setChannel(ReadableMap readableMap) {
}
}
@ReactMethod
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){
}
}
Comment on lines +106 to +130
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

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.

@ReactMethod
public void setLinkMergeEnable(boolean enable) {
JPushInterface.setLinkMergeEnable(reactContext, enable);
}

@ReactMethod
public void setSmartPushEnable(boolean enable) {
JPushInterface.setSmartPushEnable(reactContext, enable);
}

@ReactMethod
public void setDataInsightsEnable(boolean enable) {
JPushInterface.setDataInsightsEnable(reactContext, enable);
}

@ReactMethod
public void setGeofenceEnable(boolean enable) {
JPushInterface.setGeofenceEnable(reactContext, enable);
}

@ReactMethod
public void setCollectControl(ReadableMap readableMap) {
if (readableMap == null) {
JLogger.w(JConstants.PARAMS_NULL);
return;
}
boolean hadValue = false;
JPushCollectControl.Builder builder = new JPushCollectControl.Builder();
if (readableMap.hasKey(JConstants.IMEI)) {
hadValue = true;
builder.imei(readableMap.getBoolean(JConstants.IMEI));
}
if (readableMap.hasKey(JConstants.IMSI)) {
hadValue = true;
builder.imsi(readableMap.getBoolean(JConstants.IMSI));
}
if (readableMap.hasKey(JConstants.MAC)) {
hadValue = true;
builder.mac(readableMap.getBoolean(JConstants.MAC));
}
if (readableMap.hasKey(JConstants.WIFI)) {
hadValue = true;
builder.wifi(readableMap.getBoolean(JConstants.WIFI));
}
if (readableMap.hasKey(JConstants.BSSID)) {
hadValue = true;
builder.bssid(readableMap.getBoolean(JConstants.BSSID));
}
if (readableMap.hasKey(JConstants.SSID)) {
hadValue = true;
builder.ssid(readableMap.getBoolean(JConstants.SSID));
}
if (readableMap.hasKey(JConstants.CELL)) {
hadValue = true;
builder.cell(readableMap.getBoolean(JConstants.CELL));
}
if (hadValue) {
JPushInterface.setCollectControl(reactContext, builder.build());
}
}
@ReactMethod
public void setBadgeNumber(ReadableMap readableMap) {
if (readableMap == null) {
JLogger.w(JConstants.PARAMS_NULL);
Expand Down Expand Up @@ -213,7 +307,48 @@ public void filterValidTags(ReadableMap readableMap, Callback callback) {
JLogger.w("there are no " + JConstants.TAGS);
}
}
@ReactMethod
public void setProperties(ReadableMap readableMap) {
if (readableMap == null) {
JLogger.w(JConstants.PARAMS_NULL);
return;
}
if (readableMap.hasKey(JConstants.PROPERTIES)) {
int sequence = readableMap.getInt(JConstants.SEQUENCE);
ReadableMap readMap = readableMap.getMap(JConstants.PROPERTIES);
ReadableNativeMap map= (ReadableNativeMap) readMap;
HashMap properties=map.toHashMap();
JPushInterface.setProperties(reactContext,sequence,properties);
} else {
JLogger.w("there are no " + JConstants.PROPERTIES);
}
}
@ReactMethod
public void deleteProperties(ReadableMap readableMap) {
if (readableMap == null) {
JLogger.w(JConstants.PARAMS_NULL);
return;
}
if (readableMap.hasKey(JConstants.PROPERTIES)) {
int sequence = readableMap.getInt(JConstants.SEQUENCE);
ReadableMap readMap = readableMap.getMap(JConstants.PROPERTIES);
ReadableNativeMap map= (ReadableNativeMap) readMap;
HashMap properties=map.toHashMap();
JPushInterface.deleteProperties(reactContext,sequence,properties);
} else {
JLogger.w("there are no " + JConstants.PROPERTIES);
}

}
@ReactMethod
public void cleanProperties(ReadableMap readableMap) {
if (readableMap == null) {
JLogger.w(JConstants.PARAMS_NULL);
return;
}
int sequence = readableMap.getInt(JConstants.SEQUENCE);
JPushInterface.cleanProperties(reactContext,sequence);
}
Comment on lines +344 to +351
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Guard SEQUENCE in cleanProperties.

getInt throws if missing.

-        int sequence = readableMap.getInt(JConstants.SEQUENCE);
+        int sequence = readableMap.hasKey(JConstants.SEQUENCE) ? readableMap.getInt(JConstants.SEQUENCE) : -1;
📝 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.

Suggested change
public void cleanProperties(ReadableMap readableMap) {
if (readableMap == null) {
JLogger.w(JConstants.PARAMS_NULL);
return;
}
int sequence = readableMap.getInt(JConstants.SEQUENCE);
JPushInterface.cleanProperties(reactContext,sequence);
}
public void cleanProperties(ReadableMap readableMap) {
if (readableMap == null) {
JLogger.w(JConstants.PARAMS_NULL);
return;
}
int sequence = readableMap.hasKey(JConstants.SEQUENCE) ? readableMap.getInt(JConstants.SEQUENCE) : -1;
JPushInterface.cleanProperties(reactContext,sequence);
}
🤖 Prompt for AI Agents
In android/src/main/java/cn/jiguang/plugins/push/JPushModule.java around lines
344 to 351, guard access to the SEQUENCE key before calling getInt to avoid
runtime exceptions: check readableMap.hasKey(JConstants.SEQUENCE) and that it is
not null (readableMap.isNull(JConstants.SEQUENCE) == false) and optionally
verify type if available, log a warning and return when the key is
missing/invalid, then call JPushInterface.cleanProperties with the retrieved
int; do not call getInt unless the presence and non-nullity of SEQUENCE are
confirmed.

@ReactMethod
public void setTags(ReadableMap readableMap) {
if (readableMap == null) {
Expand Down Expand Up @@ -390,15 +525,61 @@ public void addLocalNotification(ReadableMap readableMap) {
int id = Integer.valueOf(notificationID);
String notificationTitle = readableMap.hasKey(JConstants.TITLE) ? readableMap.getString(JConstants.TITLE) : reactContext.getPackageName();
String notificationContent = readableMap.hasKey(JConstants.CONTENT) ? readableMap.getString(JConstants.CONTENT) : reactContext.getPackageName();
String broadcastTime = readableMap.hasKey(JConstants.BROADCAST_TIME) ? readableMap.getString(JConstants.BROADCAST_TIME) : "0";
JPushLocalNotification notification = new JPushLocalNotification();
notification.setNotificationId(id);
notification.setTitle(notificationTitle);
notification.setContent(notificationContent);
try {
notification.setBroadcastTime(Long.parseLong(broadcastTime));
}catch (Throwable throwable){
}
if (readableMap.hasKey(JConstants.EXTRAS)) {
ReadableMap notificationExtra = readableMap.getMap(JConstants.EXTRAS);
JSONObject notificationExtraJson = new JSONObject(notificationExtra.toHashMap());
notification.setExtras(notificationExtraJson.toString());
}

// 设置BuilderId
if (readableMap.hasKey(JConstants.BUILDER_NAME)) {
try {
String layoutFileName = readableMap.getString(JConstants.BUILDER_NAME);
if (!TextUtils.isEmpty(layoutFileName)) {
// 通过布局文件名获取资源ID
int builderId = reactContext.getResources().getIdentifier(
layoutFileName,
"layout",
reactContext.getPackageName()
);
if (builderId != 0) {
notification.setBuilderId(builderId);
} else {
JLogger.w("Layout file not found: " + layoutFileName);
}
}
} catch (Exception e) {
JLogger.w("Failed to set BuilderId: " + e.getMessage());
}
}

// 设置Category
if (readableMap.hasKey(JConstants.CATEGORY)) {
String category = readableMap.getString(JConstants.CATEGORY);
if (!TextUtils.isEmpty(category)) {
notification.setCategory(category);
}
}

// 设置Priority
if (readableMap.hasKey(JConstants.PRIORITY)) {
try {
int priority = readableMap.getInt(JConstants.PRIORITY);
notification.setPriority(priority);
} catch (Exception e) {
JLogger.w("Priority must be a number");
}
}

JPushInterface.addLocalNotification(reactContext, notification);
}

Expand Down
Loading