├── .gitignore ├── Doc ├── AndroidAPI.md ├── CommonAPI.md └── iOSAPI.md ├── Examples ├── PluginsDemo.cs └── launcherTemplate.gradle ├── PLuginsAndroidAARCode └── jpush-unity-plugin │ ├── .gitignore │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── libsprovided │ └── unity-classes.jar │ └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── cn │ │ └── jiguang │ │ └── unity │ │ └── push │ │ ├── JPushBridge.java │ │ ├── JPushEventReceiver.java │ │ ├── JsonUtil.java │ │ ├── PushService.java │ │ └── UnityPluginActivity.java │ └── res │ ├── drawable-hdpi │ ├── jpush_btn_bg_green_playable.xml │ ├── jpush_ic_action_cancle.png │ ├── jpush_ic_action_close.png │ ├── jpush_ic_action_close2.png │ ├── jpush_ic_richpush_actionbar_back.png │ ├── jpush_ic_richpush_actionbar_divider.png │ ├── jpush_richpush_btn_selector.xml │ └── jpush_richpush_progressbar.xml │ ├── layout-v21 │ ├── push_notification.xml │ ├── push_notification_large.xml │ └── push_notification_middle.xml │ ├── layout │ ├── jpush_inapp_banner.xml │ ├── jpush_popwin_layout.xml │ ├── jpush_webview_layout.xml │ ├── push_download_notification_layout.xml │ ├── push_notification.xml │ ├── push_notification_large.xml │ └── push_notification_middle.xml │ ├── values-zh │ └── jpush_string.xml │ ├── values │ ├── jpush_string.xml │ ├── jpush_style.xml │ └── strings.xml │ └── xml │ └── jpush_file_paths.xml ├── Plugins ├── Android │ └── jpush-unity-plugin-release.aar ├── JPushBinding.cs ├── JsonHelper.cs └── iOS │ ├── JGInforCollectionAuth.h │ ├── JPUSHService.h │ ├── JPushEventCache.h │ ├── JPushEventCache.mm │ ├── JPushUnityManager.h │ ├── JPushUnityManager.mm │ ├── libjcore-ios-3.2.9.a │ ├── libjpush-ios-4.8.1.a │ └── litjson │ ├── IJsonWrapper.cs │ ├── JsonData.cs │ ├── JsonException.cs │ ├── JsonMapper.cs │ ├── JsonReader.cs │ ├── JsonWriter.cs │ ├── Lexer.cs │ └── ParserToken.cs └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/macos,android,androidstudio 3 | 4 | ### Android ### 5 | # Built application files 6 | *.apk 7 | *.ap_ 8 | 9 | # Files for the ART/Dalvik VM 10 | *.dex 11 | 12 | # Java class files 13 | *.class 14 | 15 | # Generated files 16 | bin/ 17 | gen/ 18 | out/ 19 | 20 | # Gradle files 21 | .gradle/ 22 | build/ 23 | 24 | # Local configuration file (sdk path, etc) 25 | local.properties 26 | 27 | # Proguard folder generated by Eclipse 28 | proguard/ 29 | 30 | # Log Files 31 | *.log 32 | 33 | # Android Studio Navigation editor temp files 34 | .navigation/ 35 | 36 | # Android Studio captures folder 37 | captures/ 38 | 39 | # Intellij 40 | *.iml 41 | .idea/workspace.xml 42 | .idea/tasks.xml 43 | .idea/gradle.xml 44 | .idea/dictionaries 45 | .idea/libraries 46 | 47 | # External native build folder generated in Android Studio 2.2 and later 48 | .externalNativeBuild 49 | 50 | # Freeline 51 | freeline.py 52 | freeline/ 53 | freeline_project_description.json 54 | 55 | ### Android Patch ### 56 | gen-external-apklibs 57 | 58 | ### AndroidStudio ### 59 | # Covers files to be ignored for android development using Android Studio. 60 | 61 | # Built application files 62 | 63 | # Files for the ART/Dalvik VM 64 | 65 | # Java class files 66 | 67 | # Generated files 68 | 69 | # Gradle files 70 | .gradle 71 | 72 | # Signing files 73 | .signing/ 74 | 75 | # Local configuration file (sdk path, etc) 76 | 77 | # Proguard folder generated by Eclipse 78 | 79 | # Log Files 80 | 81 | # Android Studio 82 | /*/build/ 83 | /*/local.properties 84 | /*/out 85 | /*/*/build 86 | /*/*/production 87 | *.ipr 88 | *~ 89 | *.swp 90 | 91 | # Android Patch 92 | 93 | # External native build folder generated in Android Studio 2.2 and later 94 | 95 | # NDK 96 | obj/ 97 | 98 | # IntelliJ IDEA 99 | *.iws 100 | /out/ 101 | 102 | # User-specific configurations 103 | .idea/libraries/ 104 | .idea/.name 105 | .idea/compiler.xml 106 | .idea/copyright/profiles_settings.xml 107 | .idea/encodings.xml 108 | .idea/misc.xml 109 | .idea/modules.xml 110 | .idea/scopes/scope_settings.xml 111 | .idea/vcs.xml 112 | .idea/jsLibraryMappings.xml 113 | .idea/datasources.xml 114 | .idea/dataSources.ids 115 | .idea/sqlDataSources.xml 116 | .idea/dynamic.xml 117 | .idea/uiDesigner.xml 118 | 119 | # OS-specific files 120 | .DS_Store 121 | .DS_Store? 122 | ._* 123 | .Spotlight-V100 124 | .Trashes 125 | ehthumbs.db 126 | Thumbs.db 127 | 128 | # Legacy Eclipse project files 129 | .classpath 130 | .project 131 | .cproject 132 | .settings/ 133 | 134 | # Mobile Tools for Java (J2ME) 135 | .mtj.tmp/ 136 | 137 | # Package Files # 138 | *.war 139 | *.ear 140 | 141 | # virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml) 142 | hs_err_pid* 143 | 144 | ## Plugin-specific files: 145 | 146 | # mpeltonen/sbt-idea plugin 147 | .idea_modules/ 148 | 149 | # JIRA plugin 150 | atlassian-ide-plugin.xml 151 | 152 | # Mongo Explorer plugin 153 | .idea/mongoSettings.xml 154 | 155 | # Crashlytics plugin (for Android Studio and IntelliJ) 156 | com_crashlytics_export_strings.xml 157 | crashlytics.properties 158 | crashlytics-build.properties 159 | fabric.properties 160 | 161 | ### AndroidStudio Patch ### 162 | 163 | !/gradle/wrapper/gradle-wrapper.jar 164 | 165 | ### macOS ### 166 | *.DS_Store 167 | .AppleDouble 168 | .LSOverride 169 | 170 | # Icon must end with two \r 171 | Icon 172 | 173 | # Thumbnails 174 | 175 | # Files that might appear in the root of a volume 176 | .DocumentRevisions-V100 177 | .fseventsd 178 | .TemporaryItems 179 | .VolumeIcon.icns 180 | .com.apple.timemachine.donotpresent 181 | 182 | # Directories potentially created on remote AFP share 183 | .AppleDB 184 | .AppleDesktop 185 | Network Trash Folder 186 | Temporary Items 187 | .apdisk 188 | 189 | 190 | # End of https://www.gitignore.io/api/macos,android,androidstudio 191 | 192 | Plugins/Android/jpush-unity-plugin/\.idea/ 193 | 194 | test/ -------------------------------------------------------------------------------- /Doc/AndroidAPI.md: -------------------------------------------------------------------------------- 1 | # Android API 2 | 3 | - [停止与恢复推送服务](#停止与恢复推送服务) 4 | - [清除通知](#清除通知) 5 | - [设置允许推送时间](#设置允许推送时间) 6 | - [设置通知静默时间](#设置通知静默时间) 7 | - [申请权限接口(用于 Android 6.0 及以上系统)](#申请权限接口用于-android-60-及以上系统) 8 | - [通知栏样式定制](#通知栏样式定制) 9 | - [设置保留最近通知条数](#设置保留最近通知条数) 10 | - [本地通知](#本地通知) 11 | - [获取推送连接状态](#获取推送连接状态) 12 | - [动态设置channel](#动态设置channel) 13 | - [通知栏被打开](#通知栏被打开) 14 | - [设置地理围栏监控周期](#设置地理围栏监控周期) 15 | - [开启和关闭省电模式](#开启和关闭省电模式) 16 | 17 | 18 | ## 停止与恢复推送服务 19 | 20 | ### StopJPush() 21 | 22 | 调用了该 API 后,JPush 推送服务完全被停止。具体表现为: 23 | 24 | - JPush Service 不在后台运行; 25 | - 收不到推送消息; 26 | - 极光推送所有的其他 API 调用都无效,不能通过 InitJPush 恢复,需要调用 ResumePush 恢复。 27 | 28 | #### 代码示例 29 | 30 | ```csharp 31 | JPushBinding.StopJPush(); 32 | ``` 33 | 34 | ### ResumePush() 35 | 36 | 调用了此 API 后,极光推送完全恢复正常工作。 37 | 38 | #### 代码示例 39 | 40 | ```csharp 41 | JPushBinding.ResumeJPush(); 42 | ``` 43 | 44 | ### IsPushStopped() 45 | 46 | 调用此 API 来判断当前 Push Service 是否停止。 47 | 48 | #### 代码示例 49 | 50 | ```csharp 51 | bool isStopped = JPushBinding.IsPushStopped(); 52 | ``` 53 | 54 | #### 返回值说明 55 | 56 | - true: 调用了 stopJPush() 之后,返回 true; 57 | - false: 初始化后但没有调用 stopJPush() 之前,或者停止后再重新调用了 resumeJPush() ,返回 false; 58 | 59 | ## 清除通知 60 | 61 | ### ClearAllNotifications() 62 | 63 | 此 API 提供清除通知的功能,包括:清除所有 JPush 展现的通知(不包括非 JPush SDK 展现的)。 64 | 65 | #### 代码示例 66 | 67 | ```csharp 68 | JPushBinding.ClearAllNotifications(); 69 | ``` 70 | 71 | ### ClearNotificationById(int notiId) 72 | 73 | 此 API 用于清除指定的某个通知。 74 | 75 | #### 参数说明 76 | 77 | - notiId: 指定通知的 Notification Id。 78 | 79 | #### 代码示例 80 | 81 | ```csharp 82 | JPushBinding.ClearNotificationById(1); // 1: 指定通知的 notificationId 83 | ``` 84 | 85 | ## 设置允许推送时间 86 | 87 | ### SetPushTime(string days, int startHour, int endHour) 88 | 89 | 默认情况下用户在任何时间都允许推送。即任何时候有推送下来,客户端都会收到,并展示。 90 | 91 | 开发者可以调用此 API 来设置允许推送的时间。 92 | 93 | 如果不在该时间段内收到消息,当前的行为是:推送到的通知会被扔掉。 94 | 95 | > 这是一个纯粹客户端的实现,所以与客户端时间是否准确、时区等这些,都没有关系。 96 | 97 | #### 参数说明 98 | 99 | - days: 表示星期中的日期,0 表示星期天,1 表示星期一,以此类推。如果 days 为 null,表示任何时间都可以收到消息;如果为 "",则表示任何时间都**不能**收到消息。 100 | - startHour: 允许推送的开始时间(24小时制:范围是 0~23)。 101 | - endHour: 允许推送的结束时间(24小时制:范围是 0~23)。 102 | 103 | #### 代码示例 104 | 105 | ```csharp 106 | JPushBinding.SetPushTime("0,1,2,3", 8, 20); // 周日到周三的早上 8 点至晚上 8 点可以推送。 107 | ``` 108 | 109 | ## 设置通知静默时间 110 | 111 | ### SetSilenceTime(int startHour, int startMinute, int endHour, int endMinute) 112 | 113 | 默认情况下用户在收到推送通知时,客户端可能会有震动,响铃等提示。但用户在睡觉、开会等时间点希望为 "免打扰" 模式,也是静音时段的概念。 114 | 115 | 开发者可以调用此 API 来设置静音时段,如果在该时间段内收到消息,则:不会有铃声和震动。 116 | 117 | #### 参数说明 118 | 119 | - startHour:静默时段的开始时间 - 小时 (24小时制,范围:0 - 23)。 120 | - startMinute:静默时段的开始时间 - 分钟(范围:0 - 59)。 121 | - endHour:静默时段的结束时间 - 小时 (24小时制,范围:0 - 23)。 122 | - endMinute:静默时段的结束时间 - 分钟(范围:0 - 59)。 123 | 124 | #### 代码示例 125 | 126 | ```csharp 127 | JPushBinding.SetSilenceTime(20, 0, 7, 0); // 设置晚上 8 点至早上 7 点通知静默。 128 | ``` 129 | 130 | ## 申请权限接口(用于 Android 6.0 及以上系统) 131 | 132 | ### RequestPermission() 133 | 134 | 在 Android 6.0 及以上的系统上,需要去请求一些用到的权限,JPush SDK 用到的一些需要请求如下权限,因为需要这些权限使统计更加精准,功能更加丰富,建议开发者调用。 135 | 136 | ```xml 137 | "android.permission.READ_PHONE_STATE" 138 | "android.permission.WRITE_EXTERNAL_STORAGE" 139 | "android.permission.READ_EXTERNAL_STORAGE" 140 | "android.permission.ACCESS_FINE_LOCATION" 141 | ``` 142 | 143 | #### 代码示例 144 | 145 | ```csharp 146 | JPushBinding.RequestPermission(); 147 | ``` 148 | 149 | ## 通知栏样式定制 150 | 151 | 大多数情况下,开发者不需要调用这里的定制通知栏 API 来自定义通知栏样式,只需要使用 SDK 默认的即可。 152 | 153 | 如果想要: 154 | 155 | - 改变 Notification 里的铃声、震动、显示与消失行为; 156 | - 自定义通知栏显示样式; 157 | - 不同的 Push 通知,Notification 样式不同; 158 | - 则请使用本通知栏定制 API 提供的能力。 159 | 160 | ### SetBasicPushNotificationBuilder() 161 | 162 | 用于定制 Android Notification 里的 defaults / flags / icon 等基础样式(行为)。 163 | 164 | 具体可见[官方文档](https://docs.jiguang.cn/jpush/client/Android/android_senior/#_8)。 165 | 166 | 如果要使用,一定要修改 JPushBinding 中的 SetBasicPushNotificationBuilder 方法,去根据自己的业务逻辑修改代码。 167 | 168 | #### 代码示例 169 | 170 | ```csharp 171 | public static void SetBasicPushNotificationBuilder() 172 | { 173 | // 需要根据自己业务情况修改后再调用。 174 | int builderId = 1; // 定义该样式的 id 为 1,后台推送时就需要也设置相应推送的 builderId 为 1。 175 | int notiFlags = notificationFlags | FLAG_AUTO_CANCEL; 176 | int notiDefaults = notificationDefaults | DEFAULT_ALL; 177 | 178 | // statusBarDrawableName: 状态栏通知图标的资源文件名称(R.drawable.statusBarDrawableName)。 179 | _plugin.Call("setBasicPushNotificationBuilder", builderId, notiDefaults, notiFlags, null); 180 | } 181 | 182 | // 使用时直接调用。 183 | JPushBinding.SetBasicPushNotificationBuilder(); 184 | ``` 185 | 186 | ### SetCustomPushNotificationBuilder() 187 | 188 | 继承 Basic 进一步让开发者定制 Notification Layout。 189 | 190 | #### 代码示例 191 | 192 | ```csharp 193 | public static void SetCustomPushNotificationBuilder() 194 | { 195 | Debug.Log("unity---setCustomPushNotificationBuilder"); 196 | // 需要根据自己业务情况修改后再调用。 197 | int builderId = 1; 198 | string layoutName = "yourNotificationLayoutName"; 199 | // 指定最顶层状态栏小图标。 200 | string statusBarDrawableName = "yourStatusBarDrawableName"; 201 | // 指定下拉状态栏时显示的通知图标。 202 | string layoutIconDrawableName = "yourLayoutIconDrawableName"; 203 | 204 | _plugin.Call("setCustomPushNotificationBuilder", builderId, layoutName, statusBarDrawableName, layoutIconDrawableName); 205 | } 206 | 207 | // 使用时直接调用。 208 | JPushBinding.SetCustomPushNotificationBuilder(); 209 | ``` 210 | 211 | ## 设置保留最近通知条数 212 | 213 | ### SetLatestNotificationNumber(int num) 214 | 215 | 通过极光推送,推送了很多通知到客户端时,如果用户不去处理,就会有很多保留在那里。 216 | 217 | 此功能用于限制保留的通知条数,默认为保留最近 5 条通知。 218 | 219 | 开发者可通过调用此 API 来定义为不同的数量。 220 | 221 | > 仅对通知有效。所谓保留最近的,意思是,如果有新的通知到达,之前列表里最老的那条会被移除。 222 | 例如,设置为保留最近 5 条通知。假设已经有 5 条显示在通知栏,当第 6 条到达时,第 1 条将会被移除。 223 | 224 | #### 代码示例 225 | 226 | ```csharp 227 | JPushBinding.setLatestNotificationNumber(10); // 保留最近的 10 条通知。 228 | ``` 229 | 230 | ## 本地通知 231 | 232 | 通过极光推送的SDK,开发者只需要简单调用几个接口,便可以在应用中定时发送本地通知。 233 | 234 | > - 本地通知API不依赖于网络,无网条件下依旧可以触发。 235 | > - 本地通知与网络推送的通知是相互独立的,不受保留最近通知条数上限的限制。 236 | > - 本地通知的定时时间是自发送时算起的,不受中间关机等操作的影响。 237 | 238 | ### AddLocalNotification(int builderId, string content, string title, int notiId, int broadcastTime, string extrasJsonStr) 239 | 240 | 添加一个本地通知。 241 | 242 | #### 参数说明 243 | 244 | - builderId:通知的样式 ID,0 代表默认样式。 245 | - content:通知内容。 246 | - title:通知标题。 247 | - notiId:通知 ID。 248 | - broadcastTime:广播时间,代表从现有时间开始之后多长时间来发送这条本地通知,单位是秒。 249 | - extrasJsonStr:要在通知中附加的额外 Json 信息。 250 | 251 | #### 代码示例 252 | 253 | ```csharp 254 | // 10 秒之后触发该本地推送。 255 | JPushBinding.AddLocalNotification(0, "content", "title", 1, 10, null); 256 | ``` 257 | 258 | ### AddLocalNotificationByDate(int builderId, string content, string title, int notiId,int year, int month, int day, int hour, int minute, int second, string extrasJsonStr) 259 | 260 | 添加一个本地通知。 261 | 262 | #### 参数说明 263 | 264 | - builderId:通知的样式 ID,0 代表默认样式。 265 | - content:通知内容。 266 | - title:通知标题。 267 | - notiId:通知 ID。 268 | - year:广播时间_年。 269 | - month:广播时间_月。 270 | - day:广播时间_日。 271 | - hour:广播时间_时。 272 | - minute:广播时间_分。 273 | - second:广播时间_秒。 274 | - extrasJsonStr:要在通知中附加的额外 Json 信息。 275 | 276 | #### 代码示例 277 | 278 | ```csharp 279 | // 在 2020/1/5 12:00:00 触发该本地推送。 280 | JPushBinding.AddLocalNotificationByDate(0, "content", "title", 1, 2020, 1, 5, 12 , 0 , 0 , null); 281 | ``` 282 | 283 | ### RemoveLocalNotification(int notiId) 284 | 285 | 移除指定本地通知。 286 | 287 | #### 参数说明 288 | 289 | - notiId: 通知 Id。 290 | 291 | #### 代码示例 292 | 293 | ```csharp 294 | JPushBinding.RemoveLocalNotification(1); // 1:特定通知的 Notification ID。 295 | ``` 296 | 297 | ### ClearLocalNotifications() 298 | 299 | 清除所有本地通知。 300 | 301 | #### 代码示例 302 | 303 | ```csharp 304 | JPushBinding.ClearLocalNotifications(); 305 | ``` 306 | 307 | ## 获取推送连接状态 308 | 309 | ### GetConnectionState() 310 | 311 | 获取推送连接状态。 312 | 313 | #### 代码示例 314 | 315 | ```csharp 316 | bool isConnect = JPushBinding.GetConnectionState(); 317 | ``` 318 | 319 | 320 | ### SetChannel(string channel) 321 | 322 | 动态配置 channel 323 | 324 | #### 参数说明 325 | 326 | - channel: channel的值。 327 | 328 | 329 | ### ReportNotificationOpened(string msgId) 330 | 331 | 用于上报用户的通知栏被打开,或者用于上报用户自定义消息被展示等客户端需要统计的事件。 332 | 333 | #### 参数说明 334 | 335 | - msgId:推送每一条消息和通知对应的唯一 ID 336 | 337 | ### SetGeofenceInterval(long interval) 338 | 339 | 设置地理围栏监控周期,最小3分钟,最大1天。默认为15分钟,当距离地理围栏边界小于1000米周期自动调整为3分钟。设置成功后一直使用设置周期,不会进行调整。 340 | 341 | #### 参数说明 342 | 343 | - interval 监控周期,单位是毫秒。 344 | 345 | ### SetPowerSaveMode(bool enable) 346 | 347 | JPush SDK 开启和关闭省电模式,默认为关闭。 348 | 349 | #### 参数说明 350 | 351 | - enable 是否需要开启或关闭,true 为开启,false 为关闭 -------------------------------------------------------------------------------- /Doc/CommonAPI.md: -------------------------------------------------------------------------------- 1 | # 通用 API 2 | 3 | 以下除事件监听之外的方法都基于 `JPushBinding` 对象进行调用。 4 | 5 | - [初始化与调试](#初始化与调试) 6 | - [Init(string gameObject)](#initstring-gameobject) 7 | - [SetDebug(bool enable)](#setdebugbool-enable) 8 | - [GetRegistrationId()](#getregistrationid) 9 | - [标签与别名](#标签与别名) 10 | - [SetTags(int sequence, List tags)](#settagsint-sequence-liststring-tags) 11 | - [AddTags(int sequence, List tags)](#addtagsint-sequence-liststring-tags) 12 | - [DeleteTags(int sequence, List tags)](#deletetagsint-sequence-liststring-tags) 13 | - [CleanTags(int sequence)](#cleantagsint-sequence) 14 | - [GetAllTags(int sequence)](#getalltagsint-sequence) 15 | - [CheckTagBindState(int sequence, string tag)](#checktagbindstateint-sequence-string-tag) 16 | - [SetAlias(int sequence, string alias)](#setaliasint-sequence-string-alias) 17 | - [DeleteAlias(int sequence)](#deletealiasint-sequence) 18 | - [GetAlias(int sequence)](#getaliasint-sequence) 19 | - [FilterValidTags(List)](#filterValidTags) 20 | - [API](#API) 21 | - [SetMaxGeofenceNumber(int maxNumber)](#setMaxGeofenceNumber) 22 | - [SetMobileNumber(int sequence, string mobileNumber)](#setMobileNumber-sequence-string-mobileNumber) 23 | - [DeleteGeofence(string geofenceid)](#deleteGeofence-string-geofenceid) 24 | - [事件监听](#事件监听) 25 | - [OnReceiveNotification(string notification)](#onreceivenotificationstring-notification) 26 | - [OnReceiveMessage(string msg)](#onreceivemessagestring-msg) 27 | - [OnOpenNotification(string notification)](#onopennotificationstring-notification) 28 | - [OnJPushTagOperateResult(result)](#onjpushtagoperateresultresult) 29 | - [OnJPushAliasOperateResult(result)](#onjpushaliasoperateresultresult) 30 | - [OnMobileNumberOperatorResult(result)](#onjpushMobileNumberoperateresultresult) 31 | 32 | ## 初始化与调试 33 | 34 | ### Init(string gameObject) 35 | 36 | 插件初始化。 37 | 38 | #### 参数说明 39 | 40 | - gameObject: 代码脚本被挂载的游戏对象名。 41 | 42 | ### SetDebug(bool enable) 43 | 44 | 设置是否开启 Debug 模式。 45 | 46 | #### 参数说明 47 | 48 | - enable: 49 | - true: 开启 debug 模式,将会输出更多的 JPush 相关日志。 50 | - false: 关闭 debug 模式,建议在发布时关闭。 51 | 52 | ### GetRegistrationId() 53 | 54 | 获取当前设备的 Registration Id。 55 | 56 | ## 标签与别名 57 | 58 | 标签(tag)与别名(alias)的相关概念可查看[官方文档](https://docs.jiguang.cn/jpush/client/Android/android_senior/#_1)。 59 | 60 | ### SetTags(int sequence, List tags) 61 | 62 | 给当前设备设置标签。 63 | 64 | 注意该操作是覆盖逻辑,即每次调用会覆盖之前已经设置的标签。 65 | 66 | #### 参数说明 67 | 68 | - sequence: 作为一次操作的唯一标识,会在 `OnJPushTagOperateResult` 回调中一并返回。 69 | - tags: 标签列表。 70 | - 有效的标签组成:字母(区分大小写)、数字、下划线、汉字、特殊字符(@!#$&*+=.|)。 71 | - 限制:每个 tag 命名长度限制为 40 字节,单个设备最多支持设置 1000 个 tag,且单次操作总长度不得超过 5000 字节(判断长度需采用 UTF-8 编码)。 72 | 73 | ### AddTags(int sequence, List tags) 74 | 75 | 给当前设备在已有的基础上新增标签。 76 | 77 | #### 参数说明 78 | 79 | - sequence: 作为一次操作的唯一标识,会在 `OnJPushTagOperateResult` 回调中一并返回。 80 | - tags: 标签列表。 81 | 82 | ### DeleteTags(int sequence, List tags) 83 | 84 | 删除标签。 85 | 86 | #### 参数说明 87 | 88 | - sequence: 作为一次操作的唯一标识,会在 `OnJPushTagOperateResult` 回调中一并返回。 89 | - tags: 标签列表。 90 | 91 | ### CleanTags(int sequence) 92 | 93 | 清空标签。 94 | 95 | #### 参数说明 96 | 97 | - sequence: 作为一次操作的唯一标识,会在 `OnJPushTagOperateResult` 回调中一并返回。 98 | 99 | ### GetAllTags(int sequence) 100 | 101 | 获取当前设备的所有标签。 102 | 103 | #### 参数说明 104 | 105 | - sequence: 作为一次操作的唯一标识,会在 `OnJPushTagOperateResult` 回调中一并返回。 106 | 107 | ### CheckTagBindState(int sequence, string tag) 108 | 109 | 检查指定标签是否已经绑定。 110 | 111 | `OnJPushTagOperateResult` 回调中会附带 `isBind` 属性。 112 | 113 | #### 参数说明 114 | 115 | - sequence: 作为一次操作的唯一标识,会在 `OnJPushTagOperateResult` 回调中一并返回。 116 | - tag: 待查询的标签。 117 | 118 | ### SetAlias(int sequence, string alias) 119 | 120 | 设置别名,每个设备只会有一个别名。 121 | 122 | 注意:该接口是覆盖逻辑,即新的调用会覆盖之前的设置。 123 | 124 | #### 参数说明 125 | 126 | - sequence: 作为一次操作的唯一标识,会在 `OnJPushTagOperateResult` 回调中一并返回。 127 | - alias: 要设置的别名。 128 | - 有效的别名组成:字母(区分大小写)、数字、下划线、汉字、特殊字符(@!#$&*+=.|)。 129 | - 限制:alias 命名长度限制为 40 字节(判断长度需采用 UTF-8 编码)。 130 | 131 | ### DeleteAlias(int sequence) 132 | 133 | 删除当前设备设置的别名。 134 | 135 | #### 参数说明 136 | 137 | - sequence: 作为一次操作的唯一标识,会在 `OnJPushTagOperateResult` 回调中一并返回。 138 | 139 | ### GetAlias(int sequence) 140 | 141 | 获取当前设备设置的别名。 142 | 143 | #### 参数说明 144 | 145 | - sequence: 作为一次操作的唯一标识,会在 `OnJPushTagOperateResult` 回调中一并返回。 146 | 147 | ### FilterValidTags(List tags) 148 | 149 | 过滤非法tag 150 | 151 | #### 参数说明 152 | 153 | - tags: tag列表 154 | 155 | ## API 156 | 157 | ### SetMaxGeofenceNumber(int maxNumber) 158 | 159 | 设置最多允许保存的地理围栏数量,超过最大限制后,如果继续创建先删除最早创建的地理围栏。默认数量为10个 160 | 161 | #### 参数说明 162 | 163 | - maxNumber: 允许最大数, 164 | Andorid:允许设置最小1个,最大100个。 165 | IOS:iOS系统要求最大不能超过20个,否则会报错。 166 | 167 | ### SetMobileNumber(int sequence, string mobileNumber) 168 | 169 | 调用此 API 设置手机号码。该接口会控制调用频率,频率为 10s 之内最多 3 次。 170 | 171 | #### 参数说明 172 | 173 | - sequence: 用户自定义的操作序列号,同操作结果一起返回,用来标识一次操作的唯一性。 174 | - mobileNumber: 手机号码。如果传 null 或空串则为解除号码绑定操作。 限制:只能以 “+” 或者 数字开头;后面的内容只能包含 “-” 和数字。 175 | 176 | 177 | ### DeleteGeofence(string geofenceid) 178 | 179 | 删除地理围栏。 180 | 181 | #### 参数说明 182 | 183 | - geofenceid: 地理围栏ID. 184 | 185 | 186 | ## 事件监听 187 | 188 | 监听事件都需要在插件 `init(gameObject)` 方法传入的对应 GameObject 中实现。 189 | 190 | ### OnReceiveNotification(string notification) 191 | 192 | 收到通知。 193 | 194 | #### 参数说明 195 | 196 | - notification: 通知内容的 Json 字符串。 197 | 198 | Android 的通知内容格式为: 199 | 200 | ```text 201 | { 202 | "msgId":"信息id" 203 | "title": "通知标题", 204 | "content": "通知内容", 205 | "extras": { // 自定义键值对 206 | "key1": "value1", 207 | "key2": "value2" 208 | } 209 | ``` 210 | 211 | iOS 的通知内容格式为: 212 | 213 | ```text 214 | { 215 | "aps":{ 216 | "alert":"通知内容", 217 | "badge":1, 218 | "sound":"default" 219 | }, 220 | "key1":"value1", 221 | "key2":"value2", 222 | "_j_uid":11433016635, 223 | "_j_msgid":20266199577754012, 224 | "_j_business":1 225 | } 226 | ``` 227 | 228 | ### OnReceiveMessage(string msg) 229 | 230 | 收到自定义消息。 231 | 232 | #### 参数说明 233 | 234 | - msg: 自定义消息内容的 Json 字符串。 235 | 236 | Android 的通知内容格式为: 237 | 238 | ```text 239 | { 240 | "msgId":"信息id" 241 | "message": "自定义消息内容", 242 | "extras": { // 自定义键值对 243 | "key1": "value1", 244 | "key2": "value2" 245 | } 246 | } 247 | ``` 248 | 249 | iOS 的自定义消息内容格式为: 250 | 251 | ```text 252 | { 253 | "content": "自定义消息内容", 254 | "extras": { // 自定义键值对 255 | "key1": "value1", 256 | "key2": "value2" 257 | } 258 | } 259 | ``` 260 | 261 | ### OnOpenNotification(string notification) 262 | 263 | 点击通知栏通知事件。 264 | 265 | #### 参数说明 266 | 267 | - notification: 通知内容的 Json 字符串。 268 | 269 | Android 的通知内容格式为: 270 | 271 | ```text 272 | { 273 | "msgId":"信息id" 274 | "title": "通知标题", 275 | "content": "通知内容", 276 | "extras": { // 自定义键值对 277 | "key1": "value1", 278 | "key2": "value2" 279 | } 280 | ``` 281 | 282 | iOS 的通知内容格式为: 283 | 284 | ```text 285 | { 286 | "aps":{ 287 | "alert":"通知内容", 288 | "badge":1, 289 | "sound":"default" 290 | }, 291 | "key1":"value1", 292 | "key2":"value2", 293 | "_j_uid":11433016635, 294 | "_j_msgid":20266199577754012, 295 | "_j_business":1 296 | } 297 | ``` 298 | 299 | ### OnJPushTagOperateResult(result) 300 | 301 | JPush 的标签相关操作回调。 302 | 303 | #### 参数说明 304 | 305 | - result: Json 格式字符串。格式为: 306 | 307 | ```text 308 | { 309 | "sequence": 1, // 调用标签或别名方法时传入的。 310 | "code": 0, // 结果码。0:成功;其他:失败(详细说明可参见官网文档)。 311 | "tag": ["tag1", "tag2"], // 传入或查询得到的标签,当没有标签时,没有该字段。 312 | "isBind": true // 是否已绑定。只有调用 CheckTagBindState 方法时才有该字段。 313 | } 314 | ``` 315 | 316 | ### OnJPushAliasOperateResult(result) 317 | 318 | JPush 的别名相关操作回调。 319 | 320 | #### 参数说明 321 | 322 | - result: Json 格式字符串。格式为: 323 | 324 | ```text 325 | { 326 | "sequence": 1, // 调用标签或别名方法时传入的。 327 | "code": 0, // 结果码。0:成功;其他:失败(详细说明可参见官网文档)。 328 | "alias": "查询或传入的 alias" 329 | } 330 | ``` 331 | 332 | ### OnMobileNumberOperatorResult(result) 333 | 334 | JPush 设置电话号码回调 335 | 336 | #### 参数说明 337 | 338 | - result: Json 格式字符串。格式为: 339 | 340 | ```text 341 | { 342 | "sequence": 1, // 调用标签或别名方法时传入的。 343 | "code": 0, // 结果码。0:成功;其他:失败(详细说明可参见官网文档)。 344 | } 345 | ``` -------------------------------------------------------------------------------- /Doc/iOSAPI.md: -------------------------------------------------------------------------------- 1 | # iOS API 2 | 3 | - [iOS API](#ios-api) 4 | - [角标(badge)](#角标badge) 5 | - [SetBadge(int badge)](#setbadgeint-badge) 6 | - [参数说明](#参数说明) 7 | - [ResetBadge()](#resetbadge) 8 | - [SetApplicationIconBadgeNumber(int badge)](#setapplicationiconbadgenumberint-badge) 9 | - [参数说明](#参数说明-1) 10 | - [GetApplicationIconBadgeNumber()](#getapplicationiconbadgenumber) 11 | - [代码示例](#代码示例) 12 | - [页面统计](#页面统计) 13 | - [StartLogPageView(string pageName)](#startlogpageviewstring-pagename) 14 | - [参数说明](#参数说明-2) 15 | - [代码示例](#代码示例-1) 16 | - [StopLogPageView(string pageName)](#stoplogpageviewstring-pagename) 17 | - [参数说明](#参数说明-3) 18 | - [代码示例](#代码示例-2) 19 | - [BeginLogPageView(string pageName, int duration)](#beginlogpageviewstring-pagename-int-duration) 20 | - [参数说明](#参数说明-4) 21 | - [本地通知](#本地通知) 22 | - [SendLocalNotification(string localParams)](#sendlocalnotificationstring-localparams) 23 | - [参数说明](#参数说明-5) 24 | - [SetLocalNotification(int delay, string content, int badge, string idKey)](#setlocalnotificationint-delay-string-content-int-badge-string-idkey) 25 | - [参数说明](#参数说明-6) 26 | - [DeleteLocalNotificationWithIdentifierKey(string idKey)](#deletelocalnotificationwithidentifierkeystring-idkey) 27 | - [参数说明](#参数说明-7) 28 | - [ClearAllLocalNotifications()](#clearalllocalnotifications) 29 | - [RemoveNotification(List idKeys, bool delivered)](#removenotificationlist-idkeys-bool-delivered) 30 | - [参数说明](#参数说明-8) 31 | - [RemoveNotificationAll()](#removenotificationall) 32 | - [API](#api) 33 | - [CrashLogON()](#crashlogon) 34 | - [SetLatitude(double latitude, double longitude)](#setlatitudedouble-latitude-double-longitude) 35 | - [参数说明](#参数说明-9) 36 | 37 | ## 角标(badge) 38 | 39 | Badge 是 iOS 用来标记应用程序状态的一个数字,出现在程序图标右上角。 40 | 41 | JPush 封装了 badge 功能,允许应用上传 badge 值至 JPush 服务器,由 JPush 后台帮助管理每个用户所对应的推送 badge 值,简化了设置推送 badge 的操作。 42 | 43 | 实际应用中,开发者可以直接对 badge 值做增减操作,无需自己维护用户与 badge 值之间的对应关系。 44 | 45 | ### SetBadge(int badge) 46 | 47 | 设置 JPush 服务器中存储的角标(badge)值,该方法不会修改当前应用本地的角标值。 48 | 49 | #### 参数说明 50 | 51 | - badge: 要设置的角标值,取值范围为 0~9999。 52 | 53 | ### ResetBadge() 54 | 55 | 清空 JPush 服务器中存储的 badge 值,等同于 `SetBadge(0)`。 56 | 57 | ### SetApplicationIconBadgeNumber(int badge) 58 | 59 | 设置应用本地显示的角标值。 60 | 61 | #### 参数说明 62 | 63 | - badge: 要设置的角标值,取值范围为 0~9999。 64 | 65 | ### GetApplicationIconBadgeNumber() 66 | 67 | 获取应用当前显示的角标数。 68 | 69 | #### 代码示例 70 | 71 | ```csharp 72 | int badge = JPushBinding.GetApplicationIconBadgeNumber(); 73 | ``` 74 | 75 | ## 页面统计 76 | 77 | 用于「用户指定页面使用时长」的统计,并上报到极光服务器,在极光 Portal 上展示给开发者。页面统计集成正确,才能够获取正确的页面访问路径、访问深度(PV)的数据。 78 | 79 | ### StartLogPageView(string pageName) 80 | 81 | 进入指定页面。 82 | 83 | #### 参数说明 84 | 85 | - pageName: 指定页面名称。 86 | 87 | #### 代码示例 88 | 89 | ```csharp 90 | JPushBinding.StartLogPageView("login"); // 记录进入到 login 页面。 91 | ``` 92 | 93 | ### StopLogPageView(string pageName) 94 | 95 | 退出指定页面。 96 | 97 | #### 参数说明 98 | 99 | - pageName: 指定页面名称。 100 | 101 | #### 代码示例 102 | 103 | ```csharp 104 | JPushBinding.StopLogPageView("login"); // 记录退出 login 页面。 105 | ``` 106 | 107 | ### BeginLogPageView(string pageName, int duration) 108 | 109 | 自定义上报指定要统计的页面和用户停留的时间。 110 | 111 | #### 参数说明 112 | 113 | - pageName: 指定页面名称。 114 | - duration: 在页面停留的时间,单位秒。 115 | 116 | ## 本地通知 117 | 118 | ### SendLocalNotification(string localParams) 119 | 120 | 注册本地通知(推荐使用这个方法)。 121 | 122 | #### 参数说明 123 | 124 | - localParams 需包含如下字段 125 | - **id** : Number // 通知的 id, 可用于取消通知 126 | - **title** : String // 通知标题 127 | - **content** : String // 通知内容 128 | - **extra** : Object // extra 字段 129 | - **fireTime** : Number // 通知触发时间的时间戳(秒) 130 | - **badge** : Number // 本地推送触发后应用角标的 badge 值 (iOS Only) 131 | - **soundName** : String // 指定推送的音频文件 (iOS Only) 132 | - **subtitle** : String // 子标题 (iOS10+ Only) 133 | - **repeat**: Bool // 是否重复 (iOS Only)(注意:系统原因,设置重复触发时间必须在60s以上,否则会crash) 134 | 135 | ### SetLocalNotification(int delay, string content, int badge, string idKey) 136 | 137 | 注册本地通知(不推荐使用该方法,建议使用 SendLocalNotification)。 138 | 139 | #### 参数说明 140 | 141 | - content: 通知内容; 142 | - badge: 角标数字,如果不需要改变角标就传 -1; 143 | - idKey: 本地推送标识符。 144 | 145 | ### DeleteLocalNotificationWithIdentifierKey(string idKey) 146 | 147 | 根据推送标识删除本地通知。 148 | 149 | #### 参数说明 150 | 151 | - idKey: 本地推送标识符。 152 | 153 | ### ClearAllLocalNotifications() 154 | 155 | 清除所有注册的本地通知。 156 | 157 | ### RemoveNotification(List idKeys, bool delivered) 158 | 159 | 移除通知中心显示推送和待推送请求。 160 | 161 | #### 参数说明 162 | 163 | - idKeys: 要查找的idKey列表,null 查找所有; 164 | - badge: ture 显示的通知,false 还没有显示的通知,iOS10以下无效; 165 | 166 | ### RemoveNotificationAll() 167 | 168 | 清除所有注册的本地通知。 169 | 170 | ## API 171 | 172 | ### CrashLogON() 173 | 174 | 用于统计用户应用崩溃日志,如果需要统计 Log 信息,调用该接口。当你需要自己收集错误信息时,切记不要调用该接口。 175 | 176 | ### SetLatitude(double latitude, double longitude) 177 | 178 | 地理位置上报。 179 | 180 | #### 参数说明 181 | 182 | - latitude: 纬度; 183 | - longitude: 经度; -------------------------------------------------------------------------------- /Examples/PluginsDemo.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using JPush; 4 | using System.Collections.Generic; 5 | using System; 6 | 7 | #if UNITY_IPHONE 8 | using LitJson; 9 | #endif 10 | 11 | public class PluginsDemo : MonoBehaviour 12 | { 13 | string str_unity = ""; 14 | int callbackId = 0; 15 | 16 | // Use this for initialization 17 | void Start() 18 | { 19 | gameObject.name = "Main Camera"; 20 | JPushBinding.SetDebug(true); 21 | JPushBinding.Init(gameObject.name); 22 | } 23 | 24 | // Update is called once per frame 25 | void Update() 26 | { 27 | if(Input.GetKeyUp(KeyCode.Escape) || Input.GetKeyUp(KeyCode.Home)) 28 | { 29 | Application.Quit(); 30 | } 31 | } 32 | 33 | void OnGUI() 34 | { 35 | str_unity = GUILayout.TextField(str_unity, GUILayout.Width(Screen.width - 80), 36 | GUILayout.Height(200)); 37 | 38 | #if UNITY_ANDROID 39 | if (GUILayout.Button("stopPush", GUILayout.Height(80))) 40 | { 41 | JPushBinding.StopPush(); 42 | } 43 | 44 | if (GUILayout.Button("resumePush", GUILayout.Height(80))) 45 | { 46 | JPushBinding.ResumePush(); 47 | } 48 | #endif 49 | 50 | if (GUILayout.Button("setTags", GUILayout.Height(80))) 51 | { 52 | List tags = new List (); 53 | tags.Add("111"); 54 | tags.Add("222"); 55 | JPushBinding.SetTags(callbackId++, tags); 56 | } 57 | 58 | if (GUILayout.Button("setAlias", GUILayout.Height(80))) 59 | { 60 | JPushBinding.SetAlias(2, "replaceYourAlias"); 61 | } 62 | 63 | #if UNITY_ANDROID 64 | if (GUILayout.Button("addLocalNotification", GUILayout.Height(80))) 65 | { 66 | // JPushBinding.AddLocalNotification(0, "content", "title", 1, 0, null); 67 | JPushBinding.AddLocalNotificationByDate(0, "内容", "标题", 1, 2017, 11, 16, 13, 40, 0, ""); 68 | } 69 | #endif 70 | 71 | if (GUILayout.Button("getRegistrationId", GUILayout.Height(80))) 72 | { 73 | string registrationId = JPushBinding.GetRegistrationId(); 74 | Debug.Log("------>registrationId: " + registrationId); 75 | 76 | } 77 | 78 | if (GUILayout.Button("addTags", GUILayout.Height(80))) 79 | { 80 | List tags = new List(){"addtag1", "addtag2"}; 81 | JPushBinding.AddTags(callbackId++, tags); 82 | } 83 | 84 | if (GUILayout.Button("deleteTags", GUILayout.Height(80))) 85 | { 86 | List tags = new List(); 87 | tags.Add("addtag1"); 88 | tags.Add("addtag2"); 89 | 90 | JPushBinding.DeleteTags(callbackId++, tags); 91 | } 92 | 93 | if (GUILayout.Button("cleanTags", GUILayout.Height(80))) 94 | { 95 | JPushBinding.CleanTags(callbackId++); 96 | } 97 | 98 | if (GUILayout.Button("get all tags", GUILayout.Height(80))) 99 | { 100 | JPushBinding.GetAllTags(callbackId++); 101 | } 102 | 103 | if (GUILayout.Button("getAlias", GUILayout.Height(80))) 104 | { 105 | JPushBinding.GetAlias(callbackId++); 106 | Debug.Log("Alias 将在 OnJPushTagOperateResult 中回调"); 107 | } 108 | 109 | if (GUILayout.Button("check tag is binding", GUILayout.Height(80))) 110 | { 111 | JPushBinding.CheckTagBindState(callbackId++,"addtag1"); 112 | Debug.Log("Alias 将在 OnJPushTagOperateResult 中回调"); 113 | } 114 | 115 | if (GUILayout.Button("filterValidTags", GUILayout.Height(80))) 116 | { 117 | List tags = new List(); 118 | tags.Add("1"); 119 | tags.Add("2"); 120 | tags.Add("3"); 121 | tags.Add("4"); 122 | List reList = JPushBinding.FilterValidTags(tags); 123 | string str = string.Join(",", reList.ToArray()); 124 | Debug.Log("filterValidTags reList:" + str); 125 | str_unity = str; 126 | } 127 | 128 | if (GUILayout.Button("setMobileNumber", GUILayout.Height(80))) 129 | { 130 | JPushBinding.SetMobileNumber(callbackId++, "12345678921"); 131 | } 132 | 133 | 134 | #if UNITY_ANDROID 135 | if (GUILayout.Button("setChannel", GUILayout.Height(80))) 136 | { 137 | JPushBinding.SetChannel("unityChannel"); 138 | } 139 | 140 | #endif 141 | 142 | #if UNITY_IPHONE || UNITY_IOS 143 | if (GUILayout.Button("Trigger local notification after 3 seconds", GUILayout.Height(80))) 144 | { 145 | JsonData paramsJ = new JsonData(); 146 | paramsJ["title"] = "the title"; 147 | paramsJ["id"] = "5"; 148 | paramsJ["content"] = "the content"; 149 | paramsJ["badge"] = 9; 150 | paramsJ["repeat"] = true; 151 | TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); 152 | 153 | long ret = Convert.ToInt64(ts.TotalSeconds) + 3; 154 | paramsJ["fireTime"] = ret; 155 | paramsJ["subtitle"] = "the subtitle"; 156 | 157 | JPushBinding.SendLocalNotification(paramsJ.ToJson()); 158 | } 159 | 160 | if (GUILayout.Button("remove Notification All", GUILayout.Height(80))) 161 | { 162 | JPushBinding.RemoveNotificationAll(); 163 | } 164 | #endif 165 | } 166 | 167 | /* data format 168 | { 169 | "message": "hhh", 170 | "extras": { 171 | "f": "fff", 172 | "q": "qqq", 173 | "a": "aaa" 174 | } 175 | } 176 | */ 177 | // 开发者自己处理由 JPush 推送下来的消息。 178 | void OnReceiveMessage(string jsonStr) 179 | { 180 | Debug.Log("recv----message-----" + jsonStr); 181 | str_unity = jsonStr; 182 | } 183 | 184 | /** 185 | * { 186 | * "title": "notiTitle", 187 | * "content": "content", 188 | * "extras": { 189 | * "key1": "value1", 190 | * "key2": "value2" 191 | * } 192 | * } 193 | */ 194 | // 获取的是 json 格式数据,开发者根据自己的需要进行处理。 195 | void OnReceiveNotification(string jsonStr) 196 | { 197 | Debug.Log("recv---notification---" + jsonStr); 198 | } 199 | 200 | //开发者自己处理点击通知栏中的通知 201 | void OnOpenNotification(string jsonStr) 202 | { 203 | Debug.Log("recv---openNotification---" + jsonStr); 204 | str_unity = jsonStr; 205 | } 206 | 207 | /// 208 | /// JPush 的 tag 操作回调。 209 | /// 210 | /// 操作结果,为 json 字符串。 211 | void OnJPushTagOperateResult(string result) 212 | { 213 | Debug.Log("JPush tag operate result: " + result); 214 | str_unity = result; 215 | } 216 | 217 | /// 218 | /// JPush 的 alias 操作回调。 219 | /// 220 | /// 操作结果,为 json 字符串。 221 | void OnJPushAliasOperateResult(string result) 222 | { 223 | Debug.Log("JPush alias operate result: " + result); 224 | str_unity = result; 225 | } 226 | 227 | void OnGetRegistrationId(string result) { 228 | Debug.Log("JPush on get registration Id: " + result); 229 | str_unity = "JPush on get registration Id: " + result; 230 | } 231 | 232 | void OnMobileNumberOperatorResult(string result) 233 | { 234 | Debug.Log("JPush On Mobile Number Operator Result: " + result); 235 | str_unity = "JPush On Mobile Number Operator Result: " + result; 236 | } 237 | 238 | } 239 | -------------------------------------------------------------------------------- /Examples/launcherTemplate.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | dependencies { 4 | implementation project(':unityLibrary') 5 | 6 | implementation 'cn.jiguang.sdk:jpush:4.9.0' // 此处以JPush 4.9.0 版本为例。 7 | implementation 'cn.jiguang.sdk:jcore:4.1.0' // 此处以JCore 4.1.0 版本为例。 8 | 9 | } 10 | 11 | android { 12 | compileSdkVersion **APIVERSION** 13 | buildToolsVersion '**BUILDTOOLS**' 14 | 15 | compileOptions { 16 | sourceCompatibility JavaVersion.VERSION_1_8 17 | targetCompatibility JavaVersion.VERSION_1_8 18 | } 19 | 20 | defaultConfig { 21 | minSdkVersion **MINSDKVERSION** 22 | targetSdkVersion **TARGETSDKVERSION** 23 | applicationId '**APPLICATIONID**' 24 | ndk { 25 | abiFilters **ABIFILTERS** 26 | } 27 | versionCode **VERSIONCODE** 28 | versionName '**VERSIONNAME**' 29 | 30 | manifestPlaceholders = [ 31 | JPUSH_PKGNAME : applicationId, 32 | JPUSH_APPKEY : "你的 Appkey ", //JPush 上注册的包名对应的 Appkey. 33 | JPUSH_CHANNEL : "developer-default", //暂时填写默认值即可. 34 | ] 35 | } 36 | 37 | aaptOptions { 38 | noCompress = **BUILTIN_NOCOMPRESS** + unityStreamingAssets.tokenize(', ') 39 | ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~" 40 | }**SIGN** 41 | 42 | lintOptions { 43 | abortOnError false 44 | } 45 | 46 | buildTypes { 47 | debug { 48 | minifyEnabled **MINIFY_DEBUG** 49 | proguardFiles getDefaultProguardFile('proguard-android.txt')**SIGNCONFIG** 50 | jniDebuggable true 51 | } 52 | release { 53 | minifyEnabled **MINIFY_RELEASE** 54 | proguardFiles getDefaultProguardFile('proguard-android.txt')**SIGNCONFIG** 55 | } 56 | }**PACKAGING_OPTIONS****PLAY_ASSET_PACKS****SPLITS** 57 | **BUILT_APK_LOCATION** 58 | bundle { 59 | language { 60 | enableSplit = false 61 | } 62 | density { 63 | enableSplit = false 64 | } 65 | abi { 66 | enableSplit = true 67 | } 68 | } 69 | }**SPLITS_VERSION_CODE****LAUNCHER_SOURCE_BUILD_SETUP** 70 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/android,androidstudio 3 | 4 | ### Android ### 5 | # Built application files 6 | *.apk 7 | *.ap_ 8 | 9 | # Files for the ART/Dalvik VM 10 | *.dex 11 | 12 | # Java class files 13 | *.class 14 | 15 | # Generated files 16 | bin/ 17 | gen/ 18 | out/ 19 | 20 | # Gradle files 21 | .gradle/ 22 | build/ 23 | 24 | # Local configuration file (sdk path, etc) 25 | local.properties 26 | 27 | # Proguard folder generated by Eclipse 28 | proguard/ 29 | 30 | # Log Files 31 | *.log 32 | 33 | # Android Studio Navigation editor temp files 34 | .navigation/ 35 | 36 | # Android Studio captures folder 37 | captures/ 38 | 39 | # Intellij 40 | *.iml 41 | .idea/workspace.xml 42 | .idea/tasks.xml 43 | .idea/gradle.xml 44 | .idea/dictionaries 45 | .idea/libraries 46 | .idea 47 | 48 | # External native build folder generated in Android Studio 2.2 and later 49 | .externalNativeBuild 50 | 51 | # Freeline 52 | freeline.py 53 | freeline/ 54 | freeline_project_description.json 55 | 56 | ### Android Patch ### 57 | gen-external-apklibs 58 | 59 | ### AndroidStudio ### 60 | # Covers files to be ignored for android development using Android Studio. 61 | 62 | # Built application files 63 | 64 | # Files for the ART/Dalvik VM 65 | 66 | # Java class files 67 | 68 | # Generated files 69 | 70 | # Gradle files 71 | .gradle 72 | 73 | # Signing files 74 | .signing/ 75 | 76 | # Local configuration file (sdk path, etc) 77 | 78 | # Proguard folder generated by Eclipse 79 | 80 | # Log Files 81 | 82 | # Android Studio 83 | /*/build/ 84 | /*/local.properties 85 | /*/out 86 | /*/*/build 87 | /*/*/production 88 | *.ipr 89 | *~ 90 | *.swp 91 | 92 | # Android Patch 93 | 94 | # External native build folder generated in Android Studio 2.2 and later 95 | 96 | # NDK 97 | obj/ 98 | 99 | # IntelliJ IDEA 100 | *.iws 101 | /out/ 102 | 103 | # User-specific configurations 104 | .idea/libraries/ 105 | .idea/.name 106 | .idea/compiler.xml 107 | .idea/copyright/profiles_settings.xml 108 | .idea/encodings.xml 109 | .idea/misc.xml 110 | .idea/modules.xml 111 | .idea/scopes/scope_settings.xml 112 | .idea/vcs.xml 113 | .idea/jsLibraryMappings.xml 114 | .idea/datasources.xml 115 | .idea/dataSources.ids 116 | .idea/sqlDataSources.xml 117 | .idea/dynamic.xml 118 | .idea/uiDesigner.xml 119 | 120 | # OS-specific files 121 | .DS_Store 122 | .DS_Store? 123 | ._* 124 | .Spotlight-V100 125 | .Trashes 126 | ehthumbs.db 127 | Thumbs.db 128 | 129 | # Legacy Eclipse project files 130 | .classpath 131 | .project 132 | .cproject 133 | .settings/ 134 | 135 | # Mobile Tools for Java (J2ME) 136 | .mtj.tmp/ 137 | 138 | # Package Files # 139 | *.war 140 | *.ear 141 | 142 | # virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml) 143 | hs_err_pid* 144 | 145 | ## Plugin-specific files: 146 | 147 | # mpeltonen/sbt-idea plugin 148 | .idea_modules/ 149 | 150 | # JIRA plugin 151 | atlassian-ide-plugin.xml 152 | 153 | # Mongo Explorer plugin 154 | .idea/mongoSettings.xml 155 | 156 | # Crashlytics plugin (for Android Studio and IntelliJ) 157 | com_crashlytics_export_strings.xml 158 | crashlytics.properties 159 | crashlytics-build.properties 160 | fabric.properties 161 | 162 | ### AndroidStudio Patch ### 163 | 164 | !/gradle/wrapper/gradle-wrapper.jar 165 | 166 | 167 | # End of https://www.gitignore.io/api/android,androidstudio 168 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | mavenCentral() 6 | 7 | } 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:4.0.0' 10 | 11 | // NOTE: Do not place your application dependencies here; they belong 12 | // in the individual module build.gradle files 13 | } 14 | } 15 | 16 | apply plugin: 'com.android.library' 17 | 18 | android { 19 | compileSdkVersion 30 20 | buildToolsVersion "30.0.2" 21 | 22 | defaultConfig { 23 | minSdkVersion 14 24 | targetSdkVersion 30 25 | versionCode 1 26 | versionName "1.0" 27 | } 28 | buildTypes { 29 | release { 30 | minifyEnabled false 31 | } 32 | } 33 | compileOptions { 34 | sourceCompatibility JavaVersion.VERSION_1_8 35 | targetCompatibility JavaVersion.VERSION_1_8 36 | } 37 | 38 | lintOptions { 39 | checkReleaseBuilds false 40 | abortOnError false 41 | } 42 | } 43 | 44 | dependencies { 45 | // compile fileTree(include: ['*.jar'], dir: 'libs') 46 | compileOnly files('libsprovided/unity-classes.jar') 47 | // compile files('libs/jcore-android-2.1.2.jar') 48 | // compile files('libs/jpush-android-3.3.4.jar') 49 | 50 | compileOnly 'cn.jiguang.sdk:jpush:5.4.0' // 此处以JPush 4.9.0 版本为例。 51 | // compileOnly 'cn.jiguang.sdk:jcore:4.1.0' // 此处以JCore 4.1.0 版本为例。 52 | } 53 | 54 | repositories { 55 | flatDir{ 56 | dirs 'libs' //this way we can find the .aar file in libs folder 57 | google() 58 | jcenter() 59 | mavenCentral() 60 | } 61 | } -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/gradle.properties: -------------------------------------------------------------------------------- 1 | ## Project-wide Gradle settings. 2 | # 3 | # For more details on how to configure your build environment visit 4 | # http://www.gradle.org/docs/current/userguide/build_environment.html 5 | # 6 | # Specifies the JVM arguments used for the daemon process. 7 | # The setting is particularly useful for tweaking memory settings. 8 | # Default value: -Xmx1024m -XX:MaxPermSize=256m 9 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 10 | # 11 | # When configured, Gradle will run in incubating parallel mode. 12 | # This option should only be used with decoupled projects. More details, visit 13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 14 | # org.gradle.parallel=true 15 | #Tue Jan 30 10:16:27 CST 2018 16 | systemProp.http.proxyHost=127.0.0.1 17 | systemProp.http.proxyPort=1086 18 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jpush/jpush-unity3d-plugin/e9479fa14c9db40b14c59e8057c0a3d35207b5f1/PLuginsAndroidAARCode/jpush-unity-plugin/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Jan 30 10:16:33 CST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip 7 | 8 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/libsprovided/unity-classes.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jpush/jpush-unity3d-plugin/e9479fa14c9db40b14c59e8057c0a3d35207b5f1/PLuginsAndroidAARCode/jpush-unity-plugin/libsprovided/unity-classes.jar -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/java/cn/jiguang/unity/push/JPushBridge.java: -------------------------------------------------------------------------------- 1 | package cn.jiguang.unity.push; 2 | 3 | import android.content.Context; 4 | import android.text.TextUtils; 5 | import android.util.Log; 6 | 7 | import com.unity3d.player.UnityPlayer; 8 | 9 | import org.json.JSONArray; 10 | import org.json.JSONException; 11 | import org.json.JSONObject; 12 | 13 | import java.util.ArrayList; 14 | import java.util.HashSet; 15 | import java.util.LinkedHashSet; 16 | import java.util.List; 17 | import java.util.Set; 18 | import java.util.regex.Pattern; 19 | 20 | import cn.jiguang.api.utils.JCollectionAuth; 21 | import cn.jpush.android.api.BasicPushNotificationBuilder; 22 | import cn.jpush.android.api.CustomPushNotificationBuilder; 23 | import cn.jpush.android.api.JPushInterface; 24 | import cn.jpush.android.data.JPushLocalNotification; 25 | 26 | 27 | public class JPushBridge { 28 | 29 | private static JPushBridge jpushBridge; 30 | 31 | private Context mContext; 32 | static String gameObject; 33 | 34 | // 缓存 35 | static String openNotiStrCache; 36 | static List receiveNotiStrCache = new ArrayList(); 37 | static List receiveMessageStrCache = new ArrayList(); 38 | 39 | public static JPushBridge getInstance() { 40 | if (jpushBridge == null) { 41 | jpushBridge = new JPushBridge(); 42 | } 43 | return jpushBridge; 44 | } 45 | 46 | public void setAuth(boolean enable){ 47 | JCollectionAuth.setAuth(mContext,enable); 48 | } 49 | 50 | public void enableAutoWakeup(boolean enable){ 51 | JCollectionAuth.enableAutoWakeup(mContext,enable); 52 | } 53 | 54 | public void setDebug(boolean enable) { 55 | JPushInterface.setDebugMode(enable); 56 | } 57 | 58 | public void initPush(String gameObject) { 59 | JPushBridge.gameObject = gameObject; 60 | mContext = UnityPlayer.currentActivity.getApplicationContext(); 61 | JPushInterface.setNotificationCallBackEnable(mContext,true); 62 | JPushInterface.init(mContext); 63 | 64 | if (!receiveNotiStrCache.isEmpty()) { 65 | for (String noti : receiveNotiStrCache) { 66 | UnityPlayer.UnitySendMessage(JPushBridge.gameObject, "OnReceiveNotification", noti); 67 | } 68 | receiveNotiStrCache.clear(); 69 | } 70 | 71 | if (!TextUtils.isEmpty(openNotiStrCache)) { 72 | UnityPlayer.UnitySendMessage(JPushBridge.gameObject, "OnOpenNotification", openNotiStrCache); 73 | openNotiStrCache = null; 74 | } 75 | 76 | if (!receiveMessageStrCache.isEmpty()) { 77 | for (String msg : receiveMessageStrCache) { 78 | UnityPlayer.UnitySendMessage(JPushBridge.gameObject, "OnReceiveMessage", msg); 79 | } 80 | receiveMessageStrCache.clear(); 81 | } 82 | } 83 | 84 | public void stopPush() { 85 | JPushInterface.stopPush(mContext); 86 | } 87 | 88 | public void resumePush() { 89 | JPushInterface.resumePush(mContext); 90 | } 91 | 92 | public boolean isPushStopped() { 93 | return JPushInterface.isPushStopped(mContext); 94 | } 95 | 96 | public String getRegistrationId() { 97 | return JPushInterface.getRegistrationID(mContext); 98 | } 99 | 100 | public void initCrashHandler() { 101 | JPushInterface.initCrashHandler(mContext); 102 | } 103 | 104 | public void stopCrashHandler() { 105 | JPushInterface.stopCrashHandler(mContext); 106 | } 107 | 108 | public void setTags(int sequence, String tagsJsonStr) { 109 | if (TextUtils.isEmpty(tagsJsonStr)) { 110 | return; 111 | } 112 | 113 | Set tagSet = JsonUtil.jsonToSet(tagsJsonStr); 114 | 115 | JPushInterface.setTags(mContext, sequence, tagSet); 116 | } 117 | 118 | public void addTags(int sequence, String tagsJsonStr) { 119 | if (TextUtils.isEmpty(tagsJsonStr)) { 120 | return; 121 | } 122 | 123 | Set tagSet = JsonUtil.jsonToSet(tagsJsonStr); 124 | 125 | JPushInterface.addTags(mContext, sequence, tagSet); 126 | } 127 | 128 | 129 | 130 | public void deleteTags(int sequence, String tagsJsonStr) { 131 | if (TextUtils.isEmpty(tagsJsonStr)) { 132 | return; 133 | } 134 | 135 | Set tagSet = JsonUtil.jsonToSet(tagsJsonStr); 136 | 137 | JPushInterface.deleteTags(mContext, sequence, tagSet); 138 | } 139 | 140 | public void cleanTags(int sequence) { 141 | JPushInterface.cleanTags(mContext, sequence); 142 | } 143 | 144 | public void getAllTags(int sequence) { 145 | JPushInterface.getAllTags(mContext, sequence); 146 | } 147 | 148 | public void checkTagBindState(int sequence, String tag) { 149 | JPushInterface.checkTagBindState(mContext, sequence, tag); 150 | } 151 | 152 | public void setAlias(int sequence, String alias) { 153 | JPushInterface.setAlias(mContext, sequence, alias); 154 | } 155 | 156 | public void deleteAlias(int sequence) { 157 | JPushInterface.deleteAlias(mContext, sequence); 158 | } 159 | 160 | public void getAlias(int sequence) { 161 | JPushInterface.getAlias(mContext, sequence); 162 | } 163 | 164 | public void setPushTime(String days, int startHour, int endHour) { 165 | Set daysSet = days == null ? null : new HashSet(); 166 | 167 | if (!TextUtils.isEmpty(days)) { 168 | String[] strDays = days.split(","); 169 | for (String str : strDays) { 170 | if (!isNumeric(str)) { 171 | return; 172 | } 173 | daysSet.add(Integer.parseInt(str)); 174 | } 175 | } 176 | JPushInterface.setPushTime(mContext, daysSet, startHour, endHour); 177 | } 178 | 179 | /** 180 | * 设置通知静默时间。 181 | * 182 | * @param startHour 静音时段的开始时间 - 小时(范围:0 - 23) 183 | * @param startMinute 静音时段的开始时间 - 分钟(范围:0 - 59) 184 | * @param endHour 静音时段的结束时间 - 小时(范围:0 - 23) 185 | * @param endMinute 静音时段的结束时间 - 分钟(范围:0 - 59) 186 | */ 187 | public void setSilenceTime(int startHour, int startMinute, int endHour, int endMinute) 188 | throws Exception { 189 | if (startHour < 0 || startHour > 23 || startMinute < 0 || startMinute > 59) { 190 | throw new IllegalArgumentException("开始时间不正确"); 191 | } 192 | 193 | if (endHour < 0 || endHour > 23 || endMinute < 0 || endMinute > 59) { 194 | throw new IllegalArgumentException("结束时间不正确"); 195 | } 196 | 197 | JPushInterface.setSilenceTime(mContext, startHour, startMinute, endHour, endMinute); 198 | } 199 | 200 | public void addLocalNotification(int builderId, String content, String title, int notId, 201 | int broadcastTime, String extrasStr) { 202 | JPushLocalNotification ln = new JPushLocalNotification(); 203 | ln.setBuilderId(builderId); 204 | ln.setContent(content); 205 | ln.setTitle(title); 206 | ln.setNotificationId(notId); 207 | ln.setBroadcastTime(System.currentTimeMillis() + broadcastTime * 1000); 208 | 209 | if (!TextUtils.isEmpty(extrasStr)) { 210 | ln.setExtras(extrasStr); 211 | } 212 | 213 | JPushInterface.addLocalNotification(mContext, ln); 214 | } 215 | 216 | public void addLocalNotificationByDate(int builderId, String content, String title, int notId, 217 | int year, int month, int day, 218 | int hour, int minute, int second, String extrasStr) { 219 | JPushLocalNotification localNotification = new JPushLocalNotification(); 220 | localNotification.setBuilderId(builderId); 221 | localNotification.setContent(content); 222 | localNotification.setTitle(title); 223 | localNotification.setNotificationId(notId); 224 | localNotification.setBroadcastTime(year, month, day, hour, minute, second); 225 | 226 | if (!TextUtils.isEmpty(extrasStr)) { 227 | localNotification.setExtras(extrasStr); 228 | } 229 | 230 | JPushInterface.addLocalNotification(mContext, localNotification); 231 | } 232 | 233 | public void removeLocalNotification(int notificationId) { 234 | JPushInterface.removeLocalNotification(mContext, notificationId); 235 | } 236 | 237 | public void clearLocalNotifications() { 238 | JPushInterface.clearLocalNotifications(mContext); 239 | } 240 | 241 | public void clearAllNotifications() { 242 | JPushInterface.clearAllNotifications(mContext); 243 | } 244 | 245 | public void clearNotificationById(int notificationId) { 246 | JPushInterface.clearNotificationById(mContext, notificationId); 247 | } 248 | 249 | public void requestPermission() { 250 | UnityPlayer.currentActivity.runOnUiThread(new Runnable() { 251 | @Override 252 | public void run() { 253 | JPushInterface.requestPermission(UnityPlayer.currentActivity); 254 | } 255 | }); 256 | } 257 | 258 | /** 259 | * 设置自定义通知栏样式。 260 | * 具体可参考:https://docs.jiguang.cn/jpush/client/Android/android_senior/#_11 261 | * 262 | * @param builderId 样式 Id,代表这种通知样式,服务器推送时需要制定。 263 | * @param statusBarDrawableName 通知图片名称,需要先放在 Android 资源目录中。 264 | */ 265 | public void setBasicPushNotificationBuilder(int builderId, int notificationDefault, 266 | int notificationFlags, String statusBarDrawableName) { 267 | BasicPushNotificationBuilder builder = new BasicPushNotificationBuilder(mContext); 268 | 269 | if (notificationDefault != -1) { 270 | builder.notificationDefaults = notificationDefault; 271 | } 272 | 273 | if (notificationFlags != 16) { 274 | builder.notificationFlags = notificationFlags; 275 | } 276 | 277 | if (!TextUtils.isEmpty(statusBarDrawableName)) { 278 | builder.statusBarDrawable = getResourceId(statusBarDrawableName, "drawable"); 279 | } 280 | 281 | JPushInterface.setPushNotificationBuilder(builderId, builder); 282 | } 283 | 284 | /** 285 | * 进一步自定义通知栏,所有资源名称都需要能在资源目录中找到。 286 | * 具体可参考:https://docs.jiguang.cn/jpush/client/Android/android_senior/#_11 287 | * 288 | * @param builderId 通知栏样式编号 289 | * @param layoutName 通知布局样式名称: R.layout.layoutName 290 | * @param statusBarDrawableName 顶层状态栏小图标 291 | * @param layoutIconDrawableName 下拉状态栏时的图标 292 | */ 293 | public void setCustomPushNotificationBuilder(int builderId, String layoutName, 294 | String statusBarDrawableName, 295 | String layoutIconDrawableName) { 296 | int layoutId = getResourceId(layoutName, "layout"); 297 | int iconId = getResourceId("icon", "id"); 298 | int titleId = getResourceId("title", "id"); 299 | int textId = getResourceId("text", "id"); 300 | 301 | int statusBarDrawableId = getResourceId(statusBarDrawableName, "drawable"); 302 | int layoutIconDrawableId = getResourceId(layoutIconDrawableName, "drawable"); 303 | 304 | CustomPushNotificationBuilder builder = new CustomPushNotificationBuilder(mContext, 305 | layoutId, iconId, titleId, textId); 306 | 307 | if (statusBarDrawableId != 0) { 308 | builder.statusBarDrawable = statusBarDrawableId; 309 | } 310 | 311 | if (layoutIconDrawableId != 0) { 312 | builder.layoutIconDrawable = layoutIconDrawableId; 313 | } 314 | 315 | JPushInterface.setPushNotificationBuilder(builderId, builder); 316 | } 317 | 318 | /** 319 | * 设置最近保留的通知条数。 320 | * 321 | * @param num 保留的通知条数。 322 | */ 323 | public void setLatestNotificationNumber(int num) { 324 | JPushInterface.setLatestNotificationNumber(mContext, num); 325 | } 326 | 327 | public boolean getConnectionState() { 328 | return JPushInterface.getConnectionState(mContext); 329 | } 330 | 331 | private boolean isNumeric(String str) { 332 | Pattern pattern = Pattern.compile("[0-9]*"); 333 | return pattern.matcher(str).matches(); 334 | } 335 | 336 | private int getResourceId(String resourceName, String type) { 337 | if (TextUtils.isEmpty(resourceName)) { 338 | return 0; 339 | } 340 | return mContext.getResources().getIdentifier(resourceName, type, mContext.getPackageName()); 341 | } 342 | 343 | //新加 344 | 345 | 346 | //动态配置 channel,优先级比 AndroidManifest 里配置的高 347 | // 348 | //参数说明 349 | // 350 | //context 应用的 ApplicationContext 351 | //channel 希望配置的 channel,传 null 表示依然使用 AndroidManifest 里配置的 channel 352 | public void setChannel(String channel) { 353 | JPushInterface.setChannel(mContext, channel); 354 | } 355 | 356 | //接口返回 357 | //有效的 tag 集合。 358 | public String filterValidTags(String jsonTags) { 359 | if (null == jsonTags){ 360 | return null; 361 | } 362 | Set tags = JsonUtil.jsonToSet(jsonTags); 363 | return JsonUtil.setToJson(JPushInterface.filterValidTags(tags)); 364 | } 365 | 366 | //用于上报用户的通知栏被打开,或者用于上报用户自定义消息被展示等客户端需要统计的事件。 367 | //参数说明 368 | //context:应用的 ApplicationContext 369 | //msgId:推送每一条消息和通知对应的唯一 ID。( msgId 来源于发送消息和通知的 Extra 字段 JPushInterface.EXTRA_MSG_ID,参考 接收推送消息 Receiver ) 370 | public void reportNotificationOpened(String msgId) { 371 | JPushInterface.reportNotificationOpened(mContext, msgId); 372 | } 373 | 374 | //功能说明 375 | // 376 | //设置地理围栏监控周期,最小3分钟,最大1天。默认为15分钟,当距离地理围栏边界小于1000米周期自动调整为3分钟。设置成功后一直使用设置周期,不会进行调整。 377 | //参数说明 378 | // 379 | //context 是应用的 ApplicationContext 380 | //interval 监控周期,单位是毫秒。 381 | public void setGeofenceInterval(long interval) { 382 | JPushInterface.setGeofenceInterval(mContext, interval); 383 | } 384 | 385 | //功能说明 386 | // 387 | //设置最多允许保存的地理围栏数量,超过最大限制后,如果继续创建先删除最早创建的地理围栏。默认数量为10个,允许设置最小1个,最大100个。 388 | //参数说明 389 | // 390 | //context 是应用的 ApplicationContext 391 | //maxNumber 最多允许保存的地理围栏个数 392 | public void setMaxGeofenceNumber(int maxNumber) { 393 | JPushInterface.setMaxGeofenceNumber(mContext,maxNumber); 394 | } 395 | 396 | //删除指定id的地理围栏 397 | public void deleteGeofence(String geofenceid){ 398 | JPushInterface.deleteGeofence(mContext,geofenceid); 399 | } 400 | //调用此 API 设置手机号码。该接口会控制调用频率,频率为 10s 之内最多 3 次。 401 | //sequence 402 | //用户自定义的操作序列号,同操作结果一起返回,用来标识一次操作的唯一性。 403 | //mobileNumber 404 | //手机号码。如果传 null 或空串则为解除号码绑定操作。 405 | //限制:只能以 “+” 或者 数字开头;后面的内容只能包含 “-” 和数字。 406 | public void setMobileNumber(int sequence, String mobileNumber) { 407 | JPushInterface.setMobileNumber(mContext,sequence,mobileNumber); 408 | } 409 | 410 | //JPush SDK 开启和关闭省电模式,默认为关闭。 411 | //参数说明 412 | // 413 | //context 当前应用的 Activity 的上下文 414 | //enable 是否需要开启或关闭,true 为开启,false 为关闭 415 | public void setPowerSaveMode(boolean enable) { 416 | JPushInterface.setPowerSaveMode(mContext,enable); 417 | } 418 | 419 | 420 | 421 | } 422 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/java/cn/jiguang/unity/push/JPushEventReceiver.java: -------------------------------------------------------------------------------- 1 | package cn.jiguang.unity.push; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.text.TextUtils; 6 | import android.util.Log; 7 | 8 | import com.unity3d.player.UnityPlayer; 9 | 10 | import org.json.JSONArray; 11 | import org.json.JSONException; 12 | import org.json.JSONObject; 13 | 14 | import java.util.HashMap; 15 | import java.util.Map; 16 | import java.util.Set; 17 | 18 | import cn.jpush.android.api.CustomMessage; 19 | import cn.jpush.android.api.JPushInterface; 20 | import cn.jpush.android.api.JPushMessage; 21 | import cn.jpush.android.api.NotificationMessage; 22 | import cn.jpush.android.service.JPushMessageReceiver; 23 | 24 | /** 25 | * 处理 tag/alias 相关 API 的操作结果。 26 | */ 27 | public class JPushEventReceiver extends JPushMessageReceiver { 28 | private static final String TAG = "JPushEventReceiver"; 29 | 30 | @Override 31 | public void onTagOperatorResult(Context context, JPushMessage jPushMessage) { 32 | super.onTagOperatorResult(context, jPushMessage); 33 | 34 | JSONObject resultJson = new JSONObject(); 35 | 36 | int sequence = jPushMessage.getSequence(); 37 | try { 38 | resultJson.put("sequence", sequence); 39 | resultJson.put("code", jPushMessage.getErrorCode()); 40 | } catch (JSONException e) { 41 | e.printStackTrace(); 42 | } 43 | 44 | if (jPushMessage.getErrorCode() == 0) { // success 45 | Set tags = jPushMessage.getTags(); 46 | JSONArray tagsJsonArr = new JSONArray(); 47 | for (String tag : tags) { 48 | tagsJsonArr.put(tag); 49 | } 50 | 51 | try { 52 | if (tagsJsonArr.length() != 0) { 53 | resultJson.put("tag", tagsJsonArr); 54 | } 55 | } catch (JSONException e) { 56 | e.printStackTrace(); 57 | } 58 | } 59 | 60 | UnityPlayer.UnitySendMessage(JPushBridge.gameObject, "OnJPushTagOperateResult", resultJson.toString()); 61 | } 62 | 63 | @Override 64 | public void onCheckTagOperatorResult(Context context, JPushMessage jPushMessage) { 65 | super.onCheckTagOperatorResult(context, jPushMessage); 66 | 67 | JSONObject resultJson = new JSONObject(); 68 | 69 | int sequence = jPushMessage.getSequence(); 70 | try { 71 | resultJson.put("sequence", sequence); 72 | resultJson.put("code", jPushMessage.getErrorCode()); 73 | } catch (JSONException e) { 74 | e.printStackTrace(); 75 | } 76 | 77 | if (jPushMessage.getErrorCode() == 0) { 78 | try { 79 | resultJson.put("tag", jPushMessage.getCheckTag()); 80 | resultJson.put("isBind", jPushMessage.getTagCheckStateResult()); 81 | } catch (JSONException e) { 82 | e.printStackTrace(); 83 | } 84 | } 85 | 86 | UnityPlayer.UnitySendMessage(JPushBridge.gameObject, "OnJPushTagOperateResult", resultJson.toString()); 87 | } 88 | 89 | @Override 90 | public void onAliasOperatorResult(Context context, JPushMessage jPushMessage) { 91 | super.onAliasOperatorResult(context, jPushMessage); 92 | 93 | JSONObject resultJson = new JSONObject(); 94 | 95 | int sequence = jPushMessage.getSequence(); 96 | try { 97 | resultJson.put("sequence", sequence); 98 | resultJson.put("code", jPushMessage.getErrorCode()); 99 | } catch (JSONException e) { 100 | e.printStackTrace(); 101 | } 102 | 103 | if (jPushMessage.getErrorCode() == 0) { 104 | try { 105 | if (!TextUtils.isEmpty(jPushMessage.getAlias())) { 106 | resultJson.put("alias", jPushMessage.getAlias()); 107 | } 108 | } catch (JSONException e) { 109 | e.printStackTrace(); 110 | } 111 | } 112 | 113 | UnityPlayer.UnitySendMessage(JPushBridge.gameObject, "OnJPushAliasOperateResult", resultJson.toString()); 114 | } 115 | 116 | 117 | @Override 118 | public void onRegister(Context context, String regId) { 119 | UnityPlayer.UnitySendMessage(JPushBridge.gameObject, "OnGetRegistrationId", regId); 120 | } 121 | 122 | @Override 123 | public void onMessage(Context context, CustomMessage customMessage) { 124 | String message = customMessage.message;//bundle.getString(JPushInterface.EXTRA_MESSAGE); 125 | String extras = customMessage.extra;//bundle.getString(JPushInterface.EXTRA_EXTRA); 126 | String messageId = customMessage.messageId; 127 | String msgStr = msg2str(messageId,message, extras); 128 | if (!TextUtils.isEmpty(JPushBridge.gameObject)) { 129 | UnityPlayer.UnitySendMessage(JPushBridge.gameObject, "OnReceiveMessage", msgStr); 130 | } else { 131 | JPushBridge.receiveMessageStrCache.add(msgStr); 132 | } 133 | } 134 | 135 | @Override 136 | public void onNotifyMessageArrived(Context context, NotificationMessage notificationMessage) { 137 | super.onNotifyMessageArrived(context, notificationMessage); 138 | String content = notificationMessage.notificationContent;//bundle.getString(JPushInterface.EXTRA_ALERT); 139 | String title = notificationMessage.notificationTitle;//bundle.getString(JPushInterface.EXTRA_NOTIFICATION_TITLE); 140 | String extras = notificationMessage.notificationExtras;//bundle.getString(JPushInterface.EXTRA_EXTRA); 141 | String msgId = notificationMessage.msgId; 142 | String receiveNotiStr = noti2str(msgId,title, content, extras); 143 | 144 | Log.i(TAG, "GameObject: " + JPushBridge.gameObject); 145 | 146 | if (!TextUtils.isEmpty(JPushBridge.gameObject)) { 147 | UnityPlayer.UnitySendMessage(JPushBridge.gameObject, "OnReceiveNotification", receiveNotiStr); 148 | } else { 149 | JPushBridge.receiveNotiStrCache.add(receiveNotiStr); 150 | } 151 | } 152 | 153 | @Override 154 | public void onNotifyMessageOpened(Context context, NotificationMessage notificationMessage) { 155 | JPushInterface.reportNotificationOpened(context, notificationMessage.msgId);//bundle.getString(JPushInterface.EXTRA_MSG_ID) 156 | 157 | // Intent launch = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()); 158 | // if (launch != null) { 159 | // launch.addCategory(Intent.CATEGORY_LAUNCHER); 160 | // launch.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP); 161 | // context.startActivity(launch); 162 | // } 163 | 164 | String title = notificationMessage.notificationTitle;//bundle.getString(JPushInterface.EXTRA_NOTIFICATION_TITLE); 165 | String content = notificationMessage.notificationContent;//bundle.getString(JPushInterface.EXTRA_ALERT); 166 | String extras =notificationMessage.notificationExtras;// bundle.getString(JPushInterface.EXTRA_EXTRA); 167 | String msgId = notificationMessage.msgId; 168 | String openNotiStr = noti2str(msgId,title, content, extras); 169 | 170 | Log.i(TAG, "GameObject: " + JPushBridge.gameObject); 171 | 172 | if (!TextUtils.isEmpty(JPushBridge.gameObject)) { 173 | UnityPlayer.UnitySendMessage(JPushBridge.gameObject, "OnOpenNotification", openNotiStr); 174 | } else { 175 | JPushBridge.openNotiStrCache = openNotiStr; 176 | } 177 | } 178 | 179 | @Override 180 | public void onMobileNumberOperatorResult(Context context, JPushMessage jPushMessage) { 181 | super.onMobileNumberOperatorResult(context, jPushMessage); 182 | 183 | 184 | JSONObject resultJson = new JSONObject(); 185 | 186 | int sequence = jPushMessage.getSequence(); 187 | try { 188 | resultJson.put("sequence", sequence); 189 | resultJson.put("code", jPushMessage.getErrorCode()); 190 | } catch (JSONException e) { 191 | e.printStackTrace(); 192 | } 193 | 194 | if (jPushMessage.getErrorCode() == 0) { 195 | try { 196 | if (!TextUtils.isEmpty(jPushMessage.getMobileNumber())) { 197 | resultJson.put("mobileNumber", jPushMessage.getMobileNumber()); 198 | } 199 | } catch (JSONException e) { 200 | e.printStackTrace(); 201 | } 202 | } 203 | 204 | UnityPlayer.UnitySendMessage(JPushBridge.gameObject, "OnMobileNumberOperatorResult", resultJson.toString()); 205 | } 206 | 207 | private static String noti2str(String msgId,String title, String content, String extras) { 208 | 209 | // return ("{\"msgId:\""+msgId+"\",\"title\":\"" + title + "\",\"content\":\"" + content + "\",\"extras\":" + extras + "}"); 210 | JSONObject object=new JSONObject(); 211 | try { 212 | object.put("title",title); 213 | object.put("content",content); 214 | object.put("msgId",msgId); 215 | object.put("extras",new JSONObject(extras)); 216 | }catch (Throwable throwable){ 217 | } 218 | return object.toString(); 219 | } 220 | 221 | private static String msg2str(String msgId,String content, String extras) { 222 | // return ("{\"msgId:\""+msgId+"\",\"message\":\"" + content + "\",\"extras\":" + extras + "}"); 223 | JSONObject object=new JSONObject(); 224 | try { 225 | object.put("message",content); 226 | object.put("msgId",msgId); 227 | object.put("extras",new JSONObject(extras)); 228 | }catch (Throwable throwable){ 229 | } 230 | return object.toString(); 231 | } 232 | 233 | private static String toJson(Map jsonMap){ 234 | StringBuffer buffer = new StringBuffer(); 235 | buffer.append("{"); 236 | 237 | if (!jsonMap.isEmpty()){ 238 | Set> entries = jsonMap.entrySet(); 239 | for (Map.Entry e: 240 | entries) { 241 | String key = e.getKey(); 242 | String value = e.getValue(); 243 | buffer.append("\""); 244 | buffer.append(key); 245 | buffer.append("\""); 246 | buffer.append(":"); 247 | buffer.append("\""); 248 | buffer.append(value); 249 | buffer.append("\""); 250 | buffer.append(","); 251 | } 252 | buffer.deleteCharAt(buffer.length()-1); 253 | } 254 | 255 | buffer.append("}"); 256 | return buffer.toString(); 257 | } 258 | } -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/java/cn/jiguang/unity/push/JsonUtil.java: -------------------------------------------------------------------------------- 1 | package cn.jiguang.unity.push; 2 | 3 | import org.json.JSONArray; 4 | import org.json.JSONException; 5 | import org.json.JSONObject; 6 | 7 | import java.util.LinkedHashSet; 8 | import java.util.Set; 9 | 10 | public class JsonUtil { 11 | public static Set jsonToSet(String tagsJsonStr) { 12 | Set tagSet = new LinkedHashSet(); 13 | 14 | try { 15 | JSONObject itemsJsonObj = new JSONObject(tagsJsonStr); 16 | JSONArray tagsJsonArr = itemsJsonObj.getJSONArray("Items"); 17 | 18 | for (int i = 0; i < tagsJsonArr.length(); i++) { 19 | tagSet.add(tagsJsonArr.getString(i)); 20 | } 21 | } catch (JSONException e) { 22 | e.printStackTrace(); 23 | } 24 | return tagSet; 25 | } 26 | 27 | 28 | // {"Items":["111","222"]} 29 | 30 | public static String setToJson(Set tagSet) { 31 | if (null == tagSet || tagSet.size() == 0) { 32 | return null; 33 | } 34 | 35 | JSONObject itemsJsonObj = new JSONObject(); 36 | JSONArray tagsJsonArr = new JSONArray(); 37 | 38 | for (String tag : tagSet 39 | ) { 40 | tagsJsonArr.put(tag); 41 | } 42 | try { 43 | itemsJsonObj.put("Items", tagsJsonArr); 44 | } catch (JSONException e) { 45 | e.printStackTrace(); 46 | } 47 | return itemsJsonObj.toString(); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/java/cn/jiguang/unity/push/PushService.java: -------------------------------------------------------------------------------- 1 | package cn.jiguang.unity.push; 2 | 3 | import cn.jpush.android.service.JCommonService; 4 | 5 | public class PushService extends JCommonService { 6 | } 7 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/java/cn/jiguang/unity/push/UnityPluginActivity.java: -------------------------------------------------------------------------------- 1 | package cn.jiguang.unity.push; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.unity3d.player.UnityPlayerActivity; 6 | 7 | public class UnityPluginActivity extends UnityPlayerActivity { 8 | 9 | @Override 10 | protected void onCreate(Bundle arg0) { 11 | super.onCreate(arg0); 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/drawable-hdpi/jpush_btn_bg_green_playable.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/drawable-hdpi/jpush_ic_action_cancle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jpush/jpush-unity3d-plugin/e9479fa14c9db40b14c59e8057c0a3d35207b5f1/PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/drawable-hdpi/jpush_ic_action_cancle.png -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/drawable-hdpi/jpush_ic_action_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jpush/jpush-unity3d-plugin/e9479fa14c9db40b14c59e8057c0a3d35207b5f1/PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/drawable-hdpi/jpush_ic_action_close.png -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/drawable-hdpi/jpush_ic_action_close2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jpush/jpush-unity3d-plugin/e9479fa14c9db40b14c59e8057c0a3d35207b5f1/PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/drawable-hdpi/jpush_ic_action_close2.png -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/drawable-hdpi/jpush_ic_richpush_actionbar_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jpush/jpush-unity3d-plugin/e9479fa14c9db40b14c59e8057c0a3d35207b5f1/PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/drawable-hdpi/jpush_ic_richpush_actionbar_back.png -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/drawable-hdpi/jpush_ic_richpush_actionbar_divider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jpush/jpush-unity3d-plugin/e9479fa14c9db40b14c59e8057c0a3d35207b5f1/PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/drawable-hdpi/jpush_ic_richpush_actionbar_divider.png -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/drawable-hdpi/jpush_richpush_btn_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 14 | 15 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/drawable-hdpi/jpush_richpush_progressbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/layout-v21/push_notification.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 16 | 21 | 30 | 35 | 45 | 54 | 61 | 62 | 67 | 75 | 86 | 96 | 97 | 106 | 116 | 117 | 125 | 126 | 127 | 132 | 139 | 146 | 153 | 162 | 170 | 174 | 175 | 176 | 185 | 186 | 194 | 195 | 199 | 205 | 206 | 207 | 214 | 225 | 234 | 249 | 264 | 279 | 294 | 295 | 296 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/layout-v21/push_notification_large.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 16 | 21 | 30 | 35 | 45 | 54 | 61 | 62 | 67 | 75 | 86 | 96 | 97 | 106 | 116 | 117 | 125 | 126 | 127 | 132 | 139 | 146 | 152 | 161 | 170 | 174 | 175 | 176 | 186 | 187 | 195 | 196 | 200 | 201 | 207 | 208 | 209 | 216 | 227 | 236 | 251 | 266 | 281 | 296 | 297 | 298 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/layout-v21/push_notification_middle.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 16 | 21 | 30 | 35 | 45 | 54 | 61 | 62 | 67 | 75 | 86 | 96 | 97 | 106 | 116 | 117 | 125 | 126 | 127 | 132 | 139 | 146 | 152 | 161 | 170 | 174 | 175 | 176 | 186 | 187 | 195 | 196 | 200 | 201 | 207 | 208 | 209 | 216 | 227 | 236 | 251 | 266 | 281 | 296 | 297 | 298 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/layout/jpush_inapp_banner.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 16 | 17 | 28 | 29 | 36 | 37 | 46 | 47 | 57 | 68 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/layout/jpush_popwin_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/layout/jpush_webview_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 24 | 25 | 33 | 34 | 46 | 47 | 48 | 55 | 60 | 61 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/layout/push_download_notification_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 19 | 20 | 24 | 25 | 33 | 34 | 41 | 52 | 61 | 62 | 63 | 70 | 71 | 81 | 82 | 92 | 93 | 94 | 95 | 107 | 108 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/layout/push_notification.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 16 | 21 | 30 | 35 | 45 | 54 | 61 | 62 | 67 | 75 | 86 | 96 | 97 | 106 | 116 | 117 | 125 | 126 | 127 | 132 | 139 | 146 | 152 | 161 | 170 | 174 | 175 | 176 | 186 | 187 | 195 | 196 | 200 | 206 | 207 | 208 | 215 | 226 | 235 | 250 | 265 | 280 | 295 | 296 | 297 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/layout/push_notification_large.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 16 | 21 | 30 | 35 | 45 | 54 | 61 | 62 | 67 | 75 | 86 | 96 | 97 | 106 | 116 | 117 | 125 | 126 | 127 | 132 | 139 | 146 | 152 | 161 | 170 | 174 | 175 | 176 | 186 | 187 | 195 | 196 | 200 | 206 | 207 | 208 | 215 | 226 | 235 | 250 | 265 | 280 | 295 | 296 | 297 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/layout/push_notification_middle.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 16 | 21 | 30 | 35 | 45 | 54 | 61 | 62 | 67 | 75 | 86 | 96 | 97 | 106 | 116 | 117 | 125 | 126 | 127 | 132 | 139 | 146 | 152 | 161 | 170 | 174 | 175 | 176 | 186 | 187 | 195 | 196 | 200 | 206 | 207 | 208 | 215 | 226 | 235 | 250 | 265 | 280 | 295 | 296 | 297 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/values-zh/jpush_string.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 不重要 4 | 不重要 5 | 普通 6 | 重要 7 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/values/jpush_string.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | LOW 4 | LOW 5 | NORMAL 6 | HIGH 7 | 8 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/values/jpush_style.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 13 | 22 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | JPushUnityLibrary 3 | 4 | -------------------------------------------------------------------------------- /PLuginsAndroidAARCode/jpush-unity-plugin/src/main/res/xml/jpush_file_paths.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Plugins/Android/jpush-unity-plugin-release.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jpush/jpush-unity3d-plugin/e9479fa14c9db40b14c59e8057c0a3d35207b5f1/Plugins/Android/jpush-unity-plugin-release.aar -------------------------------------------------------------------------------- /Plugins/JsonHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using UnityEngine; 6 | 7 | namespace JPush 8 | { 9 | public static class JsonHelper 10 | { 11 | public static T[] FromJson(string json) 12 | { 13 | Wrapper wrapper = JsonUtility.FromJson>(json); 14 | return wrapper.Items; 15 | } 16 | 17 | public static string ToJson(T[] array) 18 | { 19 | Wrapper wrapper = new Wrapper 20 | { 21 | Items = array 22 | }; 23 | return JsonUtility.ToJson(wrapper); 24 | } 25 | 26 | public static string ToJson(List list) 27 | { 28 | Wrapper wrapper = new Wrapper 29 | { 30 | Items = list.ToArray() 31 | }; 32 | return JsonUtility.ToJson(wrapper); 33 | } 34 | 35 | public static string ToJson(T[] array, bool prettyPrint) 36 | { 37 | Wrapper wrapper = new Wrapper 38 | { 39 | Items = array 40 | }; 41 | return JsonUtility.ToJson(wrapper, prettyPrint); 42 | } 43 | 44 | [Serializable] 45 | private class Wrapper 46 | { 47 | public T[] Items; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Plugins/iOS/JGInforCollectionAuth.h: -------------------------------------------------------------------------------- 1 | // 2 | // JGInforCollectionAuth.h 3 | // JCore 4 | // 5 | // Created by 豆瓣 on 2021/10/27. 6 | // Copyright © 2021 jiguang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | /// 合规接口,是否授权极光采集一定的设备信息 14 | @interface JGInforCollectionAuthItems : NSObject 15 | /// 是否授权,默认YES 16 | @property(nonatomic,assign)BOOL isAuth; 17 | @end 18 | 19 | @interface JGInforCollectionAuth : NSObject 20 | 21 | /// 设备信息采集授权接口(合规接口) 22 | /// 请务必在调用初始化、功能性接口前调用此接口进行合规授权 23 | /// @param authBlock auth:YES 则极光认为您同意极光采集一定的设备信息 24 | +(void)JCollectionAuth:(void(^_Nullable)(JGInforCollectionAuthItems *authInfo))authBlock; 25 | @end 26 | 27 | NS_ASSUME_NONNULL_END 28 | -------------------------------------------------------------------------------- /Plugins/iOS/JPushEventCache.h: -------------------------------------------------------------------------------- 1 | // 2 | // JPushEventCache.h 3 | // Unity-iPhone 4 | // 5 | // Created by oshumini on 2017/12/21. 6 | // 7 | 8 | #import 9 | #import "JPUSHService.h" 10 | 11 | @interface JPushEventCache : NSObject 12 | + (JPushEventCache *)sharedInstance; 13 | 14 | - (void)sendEvent:(NSDictionary *)notification withKey:(NSString *)key; 15 | - (void)scheduleNotificationQueue; 16 | 17 | - (void)handFinishLaunchOption:(NSDictionary *)launchOptons; 18 | @end 19 | 20 | -------------------------------------------------------------------------------- /Plugins/iOS/JPushEventCache.mm: -------------------------------------------------------------------------------- 1 | // 2 | // JPushEventCache.m 3 | // Unity-iPhone 4 | // 5 | // Created by oshumini on 2017/12/21. 6 | // 7 | #import 8 | #import "JPushEventCache.h" 9 | 10 | @interface JPushEventCache() 11 | @property(strong, nonatomic) NSMutableDictionary *eventCache; 12 | @property(assign, nonatomic) BOOL isJPushDidLoad; 13 | @end 14 | 15 | @implementation JPushEventCache 16 | 17 | + (JPushEventCache *)sharedInstance { 18 | static JPushEventCache* sharedInstance = nil; 19 | static dispatch_once_t onceAPService; 20 | dispatch_once(&onceAPService, ^{ 21 | sharedInstance = [self new]; 22 | }); 23 | 24 | return sharedInstance; 25 | } 26 | 27 | - (instancetype)init { 28 | self = [super init]; 29 | if (self) { 30 | _eventCache = @{}.mutableCopy; 31 | _isJPushDidLoad = NO; 32 | } 33 | 34 | return self; 35 | } 36 | 37 | - (void)sendEvent:(NSDictionary *)userInfo withKey:(NSString *)key { 38 | if (_isJPushDidLoad) { 39 | [[NSNotificationCenter defaultCenter] postNotificationName:key object: userInfo]; 40 | return; 41 | } 42 | 43 | if (!userInfo) { 44 | return; 45 | } 46 | 47 | if (_eventCache[key]) { 48 | NSMutableArray *arr = _eventCache[key]; 49 | [arr addObject: userInfo]; 50 | } else { 51 | NSMutableArray *arr = @[].mutableCopy; 52 | _eventCache[key] = arr; 53 | [arr addObject: userInfo]; 54 | } 55 | } 56 | 57 | - (void)scheduleNotificationQueue { 58 | _isJPushDidLoad = YES; 59 | 60 | for (NSString *key in _eventCache) { 61 | for (NSDictionary *notification in _eventCache[key]) { 62 | [[NSNotificationCenter defaultCenter] postNotificationName:key object:notification]; 63 | } 64 | } 65 | [_eventCache removeAllObjects]; 66 | } 67 | 68 | - (void)handFinishLaunchOption:(NSDictionary *)launchOptons { 69 | 70 | JPUSHRegisterEntity * entity = [[JPUSHRegisterEntity alloc] init]; 71 | entity.types = JPAuthorizationOptionAlert|JPAuthorizationOptionBadge|JPAuthorizationOptionSound; 72 | [JPUSHService registerForRemoteNotificationConfig:entity delegate:[JPushEventCache sharedInstance]]; 73 | 74 | if ([[UIDevice currentDevice].systemVersion floatValue] >= 10.0) { 75 | } else { // iOS 9 and later 76 | [self sendEvent:launchOptons withKey:@"JPushPluginOpenNotification"]; 77 | } 78 | } 79 | 80 | 81 | // JPUSHRegisterDelegate 82 | // iOS 10 Support 83 | - (void)jpushNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(NSInteger))completionHandler { 84 | // Required 85 | 86 | NSMutableDictionary *userInfo = @{}.mutableCopy; 87 | if ([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) { 88 | userInfo = [NSMutableDictionary dictionaryWithDictionary: notification.request.content.userInfo]; 89 | [JPUSHService handleRemoteNotification:userInfo]; 90 | } else { 91 | UNNotificationContent *content = notification.request.content; 92 | userInfo[@"content"] = content.body; 93 | userInfo[@"badge"] = content.badge; 94 | userInfo[@"extras"] = content.userInfo; 95 | 96 | userInfo[@"identifier"] = notification.request.identifier; 97 | } 98 | [[JPushEventCache sharedInstance] sendEvent: userInfo withKey: @"JPushPluginReceiveNotification"]; 99 | 100 | 101 | // 需要执行这个方法,选择是否提醒用户,有 Badge、Sound、Alert 三种类型可以选择设置 102 | completionHandler(UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound); 103 | } 104 | 105 | // iOS 10 Support 106 | - (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler { 107 | 108 | UNNotification *notification = response.notification; 109 | NSMutableDictionary *userInfo = @{}.mutableCopy; 110 | 111 | if ([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) { 112 | userInfo = [NSMutableDictionary dictionaryWithDictionary: notification.request.content.userInfo]; 113 | [JPUSHService handleRemoteNotification:userInfo]; 114 | } else { 115 | UNNotificationContent *content = notification.request.content; 116 | 117 | userInfo[@"content"] = content.body; 118 | userInfo[@"badge"] = content.badge; 119 | userInfo[@"extras"] = content.userInfo; 120 | 121 | userInfo[@"identifier"] = notification.request.identifier; 122 | } 123 | 124 | [JPushEventCache.sharedInstance sendEvent:userInfo withKey:@"JPushPluginOpenNotification"]; 125 | completionHandler(); 126 | } 127 | @end 128 | 129 | -------------------------------------------------------------------------------- /Plugins/iOS/JPushUnityManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // JPushUnityAnalytics.h 3 | // test_certifacate 4 | // 5 | // Created by qinghe on 14-4-15. 6 | // Copyright (c) 2014年 jpush. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface JPushUnityManager : NSObject 12 | 13 | @end 14 | //extern id APNativeJSONObject(NSData *data); 15 | //extern NSData *APNativeJSONData(id obj); 16 | 17 | 18 | -------------------------------------------------------------------------------- /Plugins/iOS/libjcore-ios-3.2.9.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jpush/jpush-unity3d-plugin/e9479fa14c9db40b14c59e8057c0a3d35207b5f1/Plugins/iOS/libjcore-ios-3.2.9.a -------------------------------------------------------------------------------- /Plugins/iOS/libjpush-ios-4.8.1.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jpush/jpush-unity3d-plugin/e9479fa14c9db40b14c59e8057c0a3d35207b5f1/Plugins/iOS/libjpush-ios-4.8.1.a -------------------------------------------------------------------------------- /Plugins/iOS/litjson/IJsonWrapper.cs: -------------------------------------------------------------------------------- 1 | #region Header 2 | 3 | using System.Collections; 4 | using System.Collections.Specialized; 5 | 6 | #endregion 7 | 8 | namespace LitJson 9 | { 10 | /** 11 | */ 12 | public enum JsonType 13 | { 14 | /** 15 | */ 16 | None, 17 | 18 | /** 19 | */ 20 | Object, 21 | /** 22 | */ 23 | Array, 24 | /** 25 | */ 26 | String, 27 | /** 28 | */ 29 | Int, 30 | /** 31 | */ 32 | Long, 33 | /** 34 | */ 35 | Double, 36 | /** 37 | */ 38 | Boolean 39 | } 40 | 41 | /** 42 | * IJsonWrapper.cs 43 | * Interface that represents a type capable of handling all kinds of JSON 44 | * data. This is mainly used when mapping objects through JsonMapper, and 45 | * it's implemented by JsonData. 46 | * 47 | * The authors disclaim copyright to this source code. For more details, see 48 | * the COPYING file included with this distribution. 49 | **/ 50 | public interface IJsonWrapper : IList //, IOrderedDictionary - remove 51 | { 52 | /** 53 | */ 54 | bool IsArray { get; } 55 | /** 56 | */ 57 | bool IsBoolean { get; } 58 | /** 59 | */ 60 | bool IsDouble { get; } 61 | /** 62 | */ 63 | bool IsInt { get; } 64 | /** 65 | */ 66 | bool IsLong { get; } 67 | /** 68 | */ 69 | bool IsObject { get; } 70 | /** 71 | */ 72 | bool IsString { get; } 73 | 74 | /** 75 | */ 76 | bool GetBoolean(); 77 | /** 78 | */ 79 | double GetDouble(); 80 | /** 81 | */ 82 | int GetInt(); 83 | /** 84 | */ 85 | JsonType GetJsonType(); 86 | /** 87 | */ 88 | long GetLong(); 89 | /** 90 | */ 91 | string GetString(); 92 | 93 | /** 94 | */ 95 | void SetBoolean(bool val); 96 | /** 97 | */ 98 | void SetDouble(double val); 99 | /** 100 | */ 101 | void SetInt(int val); 102 | /** 103 | */ 104 | void SetJsonType(JsonType type); 105 | /** 106 | */ 107 | void SetLong(long val); 108 | /** 109 | */ 110 | void SetString(string val); 111 | 112 | /** 113 | */ 114 | string ToJson(); 115 | /** 116 | */ 117 | void ToJson(JsonWriter writer); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /Plugins/iOS/litjson/JsonException.cs: -------------------------------------------------------------------------------- 1 | #region Header 2 | 3 | using System; 4 | 5 | #endregion 6 | 7 | namespace LitJson 8 | { 9 | /** 10 | * JsonException.cs 11 | * Base class throwed by LitJSON when a parsing error occurs. 12 | * 13 | * The authors disclaim copyright to this source code. For more details, see 14 | * the COPYING file included with this distribution. 15 | **/ 16 | public class JsonException : ApplicationException 17 | { 18 | /** 19 | */ 20 | public JsonException() 21 | : base() 22 | { 23 | } 24 | 25 | internal JsonException (ParserToken token) : 26 | base (String.Format ( 27 | "Invalid token '{0}' in input string", token)) 28 | { 29 | } 30 | 31 | internal JsonException (ParserToken token, 32 | Exception inner_exception) : 33 | base (String.Format ( 34 | "Invalid token '{0}' in input string", token), 35 | inner_exception) 36 | { 37 | } 38 | 39 | internal JsonException (int c) : 40 | base (String.Format ( 41 | "Invalid character '{0}' in input string", (char) c)) 42 | { 43 | } 44 | 45 | internal JsonException (int c, Exception inner_exception) : 46 | base (String.Format ( 47 | "Invalid character '{0}' in input string", (char) c), 48 | inner_exception) 49 | { 50 | } 51 | 52 | 53 | /** 54 | */ 55 | public JsonException(string message) 56 | : base(message) 57 | { 58 | } 59 | 60 | /** 61 | */ 62 | public JsonException(string message, Exception inner_exception) : 63 | base (message, inner_exception) 64 | { 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Plugins/iOS/litjson/JsonWriter.cs: -------------------------------------------------------------------------------- 1 | #region Header 2 | 3 | using System; 4 | using System.Collections; 5 | using System.Globalization; 6 | using System.IO; 7 | using System.Text; 8 | 9 | #endregion 10 | 11 | namespace LitJson 12 | { 13 | internal enum Condition 14 | { 15 | InArray, 16 | InObject, 17 | NotAProperty, 18 | Property, 19 | Value 20 | } 21 | 22 | internal class WriterContext 23 | { 24 | public int Count; 25 | public bool InArray; 26 | public bool InObject; 27 | public bool ExpectingValue; 28 | public int Padding; 29 | } 30 | 31 | /** 32 | * JsonWriter.cs 33 | * Stream-like facility to output JSON text. 34 | * 35 | * This file was modified from the original to not use System.Collection.Generics namespace. 36 | * 37 | * The authors disclaim copyright to this source code. For more details, see 38 | * the COPYING file included with this distribution. 39 | **/ 40 | public class JsonWriter 41 | { 42 | #region Fields 43 | private static NumberFormatInfo number_format; 44 | 45 | private WriterContext context; 46 | private Stack ctx_stack; 47 | private bool has_reached_end; 48 | private char[] hex_seq; 49 | private int indentation; 50 | private int indent_value; 51 | private StringBuilder inst_string_builder; 52 | private bool pretty_print; 53 | private bool validate; 54 | private TextWriter writer; 55 | #endregion 56 | 57 | 58 | #region Properties 59 | /** 60 | */ 61 | public int IndentValue { 62 | get { return indent_value; } 63 | set { 64 | indentation = (indentation / indent_value) * value; 65 | indent_value = value; 66 | } 67 | } 68 | 69 | /** 70 | */ 71 | public bool PrettyPrint { 72 | get { return pretty_print; } 73 | set { pretty_print = value; } 74 | } 75 | 76 | /** 77 | */ 78 | public TextWriter TextWriter { 79 | get { return writer; } 80 | } 81 | 82 | /** 83 | */ 84 | public bool Validate { 85 | get { return validate; } 86 | set { validate = value; } 87 | } 88 | #endregion 89 | 90 | 91 | #region Constructors 92 | static JsonWriter () 93 | { 94 | number_format = NumberFormatInfo.InvariantInfo; 95 | } 96 | 97 | /** 98 | */ 99 | public JsonWriter() 100 | { 101 | inst_string_builder = new StringBuilder (); 102 | writer = new StringWriter (inst_string_builder); 103 | 104 | Init (); 105 | } 106 | 107 | /** 108 | */ 109 | public JsonWriter(StringBuilder sb) : 110 | this (new StringWriter (sb)) 111 | { 112 | } 113 | 114 | /** 115 | */ 116 | public JsonWriter(TextWriter writer) 117 | { 118 | if (writer == null) 119 | throw new ArgumentNullException ("writer"); 120 | 121 | this.writer = writer; 122 | 123 | Init (); 124 | } 125 | #endregion 126 | 127 | 128 | #region Private Methods 129 | private void DoValidation (Condition cond) 130 | { 131 | if (! context.ExpectingValue) 132 | context.Count++; 133 | 134 | if (! validate) 135 | return; 136 | 137 | if (has_reached_end) 138 | throw new JsonException ( 139 | "A complete JSON symbol has already been written"); 140 | 141 | switch (cond) { 142 | case Condition.InArray: 143 | if (! context.InArray) 144 | throw new JsonException ( 145 | "Can't close an array here"); 146 | break; 147 | 148 | case Condition.InObject: 149 | if (! context.InObject || context.ExpectingValue) 150 | throw new JsonException ( 151 | "Can't close an object here"); 152 | break; 153 | 154 | case Condition.NotAProperty: 155 | if (context.InObject && ! context.ExpectingValue) 156 | throw new JsonException ( 157 | "Expected a property"); 158 | break; 159 | 160 | case Condition.Property: 161 | if (! context.InObject || context.ExpectingValue) 162 | throw new JsonException ( 163 | "Can't add a property here"); 164 | break; 165 | 166 | case Condition.Value: 167 | if (! context.InArray && 168 | (! context.InObject || ! context.ExpectingValue)) 169 | throw new JsonException ( 170 | "Can't add a value here"); 171 | 172 | break; 173 | } 174 | } 175 | 176 | private void Init () 177 | { 178 | has_reached_end = false; 179 | hex_seq = new char[4]; 180 | indentation = 0; 181 | indent_value = 4; 182 | pretty_print = false; 183 | validate = true; 184 | 185 | ctx_stack = new Stack(); 186 | context = new WriterContext (); 187 | ctx_stack.Push (context); 188 | } 189 | 190 | private static void IntToHex (int n, char[] hex) 191 | { 192 | int num; 193 | 194 | for (int i = 0; i < 4; i++) { 195 | num = n % 16; 196 | 197 | if (num < 10) 198 | hex[3 - i] = (char) ('0' + num); 199 | else 200 | hex[3 - i] = (char) ('A' + (num - 10)); 201 | 202 | n >>= 4; 203 | } 204 | } 205 | 206 | private void Indent () 207 | { 208 | if (pretty_print) 209 | indentation += indent_value; 210 | } 211 | 212 | 213 | private void Put (string str) 214 | { 215 | if (pretty_print && ! context.ExpectingValue) 216 | for (int i = 0; i < indentation; i++) 217 | writer.Write (' '); 218 | 219 | writer.Write (str); 220 | } 221 | 222 | private void PutNewline () 223 | { 224 | PutNewline (true); 225 | } 226 | 227 | private void PutNewline (bool add_comma) 228 | { 229 | if (add_comma && ! context.ExpectingValue && 230 | context.Count > 1) 231 | writer.Write (','); 232 | 233 | if (pretty_print && ! context.ExpectingValue) 234 | writer.Write ('\n'); 235 | } 236 | 237 | private void PutString (string str) 238 | { 239 | Put (String.Empty); 240 | 241 | writer.Write ('"'); 242 | 243 | int n = str.Length; 244 | for (int i = 0; i < n; i++) { 245 | switch (str[i]) { 246 | case '\n': 247 | writer.Write ("\\n"); 248 | continue; 249 | 250 | case '\r': 251 | writer.Write ("\\r"); 252 | continue; 253 | 254 | case '\t': 255 | writer.Write ("\\t"); 256 | continue; 257 | 258 | case '"': 259 | case '\\': 260 | writer.Write ('\\'); 261 | writer.Write (str[i]); 262 | continue; 263 | 264 | case '\f': 265 | writer.Write ("\\f"); 266 | continue; 267 | 268 | case '\b': 269 | writer.Write ("\\b"); 270 | continue; 271 | } 272 | 273 | if ((int) str[i] >= 32 && (int) str[i] <= 126) { 274 | writer.Write (str[i]); 275 | continue; 276 | } 277 | 278 | // Default, turn into a \uXXXX sequence 279 | IntToHex ((int) str[i], hex_seq); 280 | writer.Write ("\\u"); 281 | writer.Write (hex_seq); 282 | } 283 | 284 | writer.Write ('"'); 285 | } 286 | 287 | private void Unindent () 288 | { 289 | if (pretty_print) 290 | indentation -= indent_value; 291 | } 292 | #endregion 293 | 294 | 295 | /** 296 | */ 297 | public override string ToString() 298 | { 299 | if (inst_string_builder == null) 300 | return String.Empty; 301 | 302 | return inst_string_builder.ToString (); 303 | } 304 | 305 | /** 306 | */ 307 | public void Reset() 308 | { 309 | has_reached_end = false; 310 | 311 | ctx_stack.Clear (); 312 | context = new WriterContext (); 313 | ctx_stack.Push (context); 314 | 315 | if (inst_string_builder != null) 316 | inst_string_builder.Remove (0, inst_string_builder.Length); 317 | } 318 | 319 | /** 320 | */ 321 | public void Write(bool boolean) 322 | { 323 | DoValidation (Condition.Value); 324 | PutNewline (); 325 | 326 | Put (boolean ? "true" : "false"); 327 | 328 | context.ExpectingValue = false; 329 | } 330 | 331 | /** 332 | */ 333 | public void Write(decimal number) 334 | { 335 | DoValidation (Condition.Value); 336 | PutNewline (); 337 | 338 | Put (Convert.ToString (number, number_format)); 339 | 340 | context.ExpectingValue = false; 341 | } 342 | 343 | /** 344 | */ 345 | public void Write(double number) 346 | { 347 | DoValidation (Condition.Value); 348 | PutNewline (); 349 | 350 | string str = Convert.ToString (number, number_format); 351 | Put (str); 352 | 353 | if (str.IndexOf ('.') == -1 && 354 | str.IndexOf ('E') == -1) 355 | writer.Write (".0"); 356 | 357 | context.ExpectingValue = false; 358 | } 359 | 360 | /** 361 | */ 362 | public void Write(int number) 363 | { 364 | DoValidation (Condition.Value); 365 | PutNewline (); 366 | 367 | Put (Convert.ToString (number, number_format)); 368 | 369 | context.ExpectingValue = false; 370 | } 371 | 372 | /** 373 | */ 374 | public void Write(long number) 375 | { 376 | DoValidation (Condition.Value); 377 | PutNewline (); 378 | 379 | Put (Convert.ToString (number, number_format)); 380 | 381 | context.ExpectingValue = false; 382 | } 383 | 384 | /** 385 | */ 386 | public void Write(string str) 387 | { 388 | DoValidation (Condition.Value); 389 | PutNewline (); 390 | 391 | if (str == null) 392 | Put ("null"); 393 | else 394 | PutString (str); 395 | 396 | context.ExpectingValue = false; 397 | } 398 | 399 | /** 400 | */ 401 | public void Write(ulong number) 402 | { 403 | DoValidation (Condition.Value); 404 | PutNewline (); 405 | 406 | Put (Convert.ToString (number, number_format)); 407 | 408 | context.ExpectingValue = false; 409 | } 410 | 411 | /** 412 | */ 413 | public void WriteArrayEnd() 414 | { 415 | DoValidation (Condition.InArray); 416 | PutNewline (false); 417 | 418 | ctx_stack.Pop(); 419 | if (ctx_stack.Count == 1) 420 | has_reached_end = true; 421 | else { 422 | context = ctx_stack.Peek() as WriterContext; 423 | context.ExpectingValue = false; 424 | } 425 | 426 | Unindent (); 427 | Put ("]"); 428 | } 429 | 430 | /** 431 | */ 432 | public void WriteArrayStart() 433 | { 434 | DoValidation (Condition.NotAProperty); 435 | PutNewline (); 436 | 437 | Put ("["); 438 | 439 | context = new WriterContext (); 440 | context.InArray = true; 441 | ctx_stack.Push (context); 442 | 443 | Indent (); 444 | } 445 | 446 | /** 447 | */ 448 | public void WriteObjectEnd() 449 | { 450 | DoValidation (Condition.InObject); 451 | PutNewline (false); 452 | 453 | ctx_stack.Pop (); 454 | if (ctx_stack.Count == 1) 455 | has_reached_end = true; 456 | else { 457 | context = ctx_stack.Peek() as WriterContext; 458 | context.ExpectingValue = false; 459 | } 460 | 461 | Unindent (); 462 | Put ("}"); 463 | } 464 | 465 | /** 466 | */ 467 | public void WriteObjectStart() 468 | { 469 | DoValidation (Condition.NotAProperty); 470 | PutNewline (); 471 | 472 | Put ("{"); 473 | 474 | context = new WriterContext (); 475 | context.InObject = true; 476 | ctx_stack.Push (context); 477 | 478 | Indent (); 479 | } 480 | 481 | /** 482 | */ 483 | public void WritePropertyName(string property_name) 484 | { 485 | DoValidation (Condition.Property); 486 | PutNewline (); 487 | 488 | PutString (property_name); 489 | 490 | if (pretty_print) { 491 | if (property_name.Length > context.Padding) 492 | context.Padding = property_name.Length; 493 | 494 | for (int i = context.Padding - property_name.Length; 495 | i >= 0; i--) 496 | writer.Write (' '); 497 | 498 | writer.Write (": "); 499 | } else 500 | writer.Write (':'); 501 | 502 | context.ExpectingValue = true; 503 | } 504 | } 505 | } 506 | -------------------------------------------------------------------------------- /Plugins/iOS/litjson/ParserToken.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace LitJson 3 | { 4 | /** 5 | * ParserToken.cs 6 | * Internal representation of the tokens used by the lexer and the parser. 7 | * 8 | * The authors disclaim copyright to this source code. For more details, see 9 | * the COPYING file included with this distribution. 10 | **/ 11 | internal enum ParserToken 12 | { 13 | // Lexer tokens 14 | None = System.Char.MaxValue + 1, 15 | Number, 16 | True, 17 | False, 18 | Null, 19 | CharSeq, 20 | // Single char 21 | Char, 22 | 23 | // Parser Rules 24 | Text, 25 | Object, 26 | ObjectPrime, 27 | Pair, 28 | PairRest, 29 | Array, 30 | ArrayPrime, 31 | Value, 32 | ValueRest, 33 | String, 34 | 35 | // End of input 36 | End, 37 | 38 | // The empty rule 39 | Epsilon 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JPush Unity Plugin 2 | 3 | [![release](https://img.shields.io/badge/release-3.2.0-blue.svg)](https://github.com/jpush/jpush-unity3d-plugin/releases) 4 | [![platforms](https://img.shields.io/badge/platforms-iOS%7CAndroid-green.svg)](https://github.com/jpush/jpush-unity3d-plugin) 5 | 6 | 这是极光官方支持的 JPush Unity 插件(Android & iOS)。 7 | 8 | ## 集成 9 | 10 | 把Plugins文件夹里的文件合并到您自己的项目Assets/Plugins文件夹下面 11 | 12 | ### Android 13 | 14 | 1. 生成build文件: 15 | 在 Unity 中选择 *File---Build Settings---Player Settings* 16 | ---Publishing Settings ---- Build 勾上选以下选项下: 17 | * Custom Launcher Gradle Template 18 | ##### 会生成以下文件 19 | * launcherTemplate.gradle文件 20 | #### 修改launcherTemplate.gradle文件: 21 | - 在dependencies里面加 22 | ``` 23 | implementation 'cn.jiguang.sdk:jpush:4.9.0' // 此处以JPush 4.9.0 版本为例。 24 | implementation 'cn.jiguang.sdk:jcore:4.1.0' // 此处以JCore 4.1.0 版本为例。 25 | ``` 26 | - 在defaultConfig里面加,并填写对应信息 27 | ``` 28 | manifestPlaceholders = [ 29 | JPUSH_PKGNAME : applicationId, 30 | JPUSH_APPKEY : "你的 Appkey ", //JPush 上注册的包名对应的 Appkey. 31 | JPUSH_CHANNEL : "developer-default", //暂时填写默认值即可. 32 | ] 33 | ``` 34 | 具体可参考Examples下 launcherTemplate.gradle 文件 35 | 36 | 2. 配置项目里的包名:在 Unity 中选择 *File---Build Settings---Player Settings*,将 *Identification* 选项下的 *Bundle Identifier* 设置为应用的包名。 37 | 38 | ### iOS 39 | 40 | 1. 生成 iOS 工程,并打开该工程。 41 | 2. 添加必要的框架: 42 | - CFNetwork.framework 43 | - CoreFoundation.framework 44 | - CoreTelephony.framework 45 | - SystemConfiguration.framework 46 | - CoreGraphics.framework 47 | - Foundation.framework 48 | - UIKit.framework 49 | - Security.framework 50 | - libz.tbd(Xcode 7 以下版本是 libz.dylib) 51 | - AdSupport.framework(获取 IDFA 需要;如果不使用 IDFA,请不要添加) 52 | - UserNotifications.framework(Xcode 8 及以上) 53 | - libresolv.tbd(JPush 2.2.0 及以上版本需要,Xcode 7 以下版本是 libresolv.dylib) 54 | - WebKit.framework(JPush 3.3.0 及以上版本需要) 55 | - AppTrackingTransparency.framework(Xcode 12 及以上,获取 IDFA 需要;如果不使用 IDFA,请不要添加) 56 | - StoreKit.framework(JPush 3.3.6 及以上版本需要) 57 | 58 | 59 | ​ 60 | 61 | 3. 在 UnityAppController.mm 中添加头文件 `JPUSHService.h` 。 62 | 63 | ```Objective-C 64 | #import "JPUSHService.h" 65 | #import "JPushEventCache.h" 66 | #import 67 | 68 | // 如需使用广告标识符 IDFA 则添加该头文件,否则不添加。 69 | #import 70 | 71 | @interface UnityAppController () 72 | @end 73 | ``` 74 | 75 | 4. 在 UnityAppController.mm 的下列方法中添加以下代码: 76 | 77 | ```Objective-C 78 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 79 | 80 | [[JPushEventCache sharedInstance] handFinishLaunchOption:launchOptions]; 81 | /* 82 | 不使用 IDFA 启动 SDK。 83 | 参数说明: 84 | appKey: 极光官网控制台应用标识。 85 | channel: 频道,暂无可填任意。 86 | apsForProduction: YES: 发布环境;NO: 开发环境。 87 | */ 88 | [JPUSHService setupWithOption:launchOptions appKey:@"abcacdf406411fa656ee11c3" channel:@"" apsForProduction:NO]; 89 | 90 | /* 91 | 使用 IDFA 启动 SDK(不能与上述方法同时使用)。 92 | 参数说明: 93 | appKey: 极光官网控制台应用标识。 94 | channel: 频道,暂无可填任意。 95 | apsForProduction: YES: 发布环境;NO: 开发环境。 96 | advertisingIdentifier: IDFA广告标识符。根据自身情况选择是否带有 IDFA 的启动方法,并注释另外一个启动方法。 97 | */ 98 | // NSString *advertisingId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString]; 99 | // [JPUSHService setupWithOption:launchOptions appKey:@"替换成你自己的 Appkey" channel:@"" apsForProduction:NO SadvertisingIdentifier:advertisingId]; 100 | 101 | return YES; 102 | } 103 | 104 | - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { 105 | // Required. 106 | [JPUSHService registerDeviceToken:deviceToken]; 107 | } 108 | 109 | - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { 110 | // Required. 111 | [[JPushEventCache sharedInstance] sendEvent:userInfo withKey:@"JPushPluginReceiveNotification"]; 112 | [JPUSHService handleRemoteNotification:userInfo]; 113 | } 114 | 115 | - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler { 116 | [[JPushEventCache sharedInstance] sendEvent:userInfo withKey:@"JPushPluginReceiveNotification"]; 117 | } 118 | ``` 119 | 120 | 5.有些Unity版本在导出Xcode项目之后,需要修改: 121 | 122 | ```Objective-C 123 | Preprocessor.h 文件中 124 | 125 | #define UNITY_USES_REMOTE_NOTIFICATIONS 0 126 | 更改为 127 | #define UNITY_USES_REMOTE_NOTIFICATIONS 1 128 | 129 | 否则 130 | 131 | didReceiveRemoteNotification 132 | didRegisterForRemoteNotificationsWithDeviceToken 133 | didReceiveRemoteNotification 134 | 135 | 都将无法使用 136 | ``` 137 | ## API 说明 138 | 139 | Android 与 iOS [通用 API](/Doc/CommonAPI.md)。 140 | 141 | ### Android 142 | 143 | [Android API](/Doc/AndroidAPI.md) 144 | 145 | > ./Plugins/Android/jpush-unity-plugin 为插件的 Android 项目,可以使用 Android Studio 打开并进行修改(比如,targetSdkVersion 或者 minSdkVersion),再 build 为 .aar 替换已有的 jpush.aar。 146 | 147 | ### iOS 148 | 149 | [iOS API](/Doc/iOSAPI.md) 150 | 151 | ## 更多 152 | 153 | - [JPush 官网文档](http://docs.jiguang.cn/guideline/jpush_guide/) 154 | - 有问题可访问[极光社区](http://community.jpush.cn/)搜索和提问。 155 | --------------------------------------------------------------------------------