├── .github └── ISSUE_TEMPLATE │ └── issue-with-the-sample-code.md ├── .gitignore ├── 3rd-party └── .gitignore ├── LICENSE ├── README.md ├── README_ZH.md ├── Third Party Open Source Software Notice.docx ├── build └── .gitignore ├── dist └── .gitignore ├── doc └── .gitignore ├── pom.xml ├── src └── main │ ├── java │ └── com │ │ └── huawei │ │ └── push │ │ ├── android │ │ ├── AndroidNotification.java │ │ ├── BadgeNotification.java │ │ ├── Button.java │ │ ├── ClickAction.java │ │ ├── Color.java │ │ └── LightSettings.java │ │ ├── apns │ │ ├── Alert.java │ │ ├── ApnsHeaders.java │ │ ├── ApnsHmsOptions.java │ │ └── Aps.java │ │ ├── examples │ │ ├── SendApnsMessage.java │ │ ├── SendConditionMessage.java │ │ ├── SendDataMessage.java │ │ ├── SendInstanceAppMessage.java │ │ ├── SendNotifyMessage.java │ │ ├── SendTestMessage.java │ │ ├── SendTopicMessage.java │ │ └── SendWebpushMessage.java │ │ ├── exception │ │ ├── HuaweiException.java │ │ └── HuaweiMesssagingException.java │ │ ├── message │ │ ├── AndroidConfig.java │ │ ├── ApnsConfig.java │ │ ├── Message.java │ │ ├── Notification.java │ │ ├── TokenMessage.java │ │ ├── TopicMessage.java │ │ └── WebPushConfig.java │ │ ├── messaging │ │ ├── HuaweiApp.java │ │ ├── HuaweiCredential.java │ │ ├── HuaweiMessageClient.java │ │ ├── HuaweiMessageClientImpl.java │ │ ├── HuaweiMessaging.java │ │ ├── HuaweiOption.java │ │ ├── HuaweiScheduledExecutor.java │ │ ├── HuaweiService.java │ │ ├── HuaweiThreadManager.java │ │ ├── ImplHuaweiTrampolines.java │ │ ├── ThreadManager.java │ │ └── TokenRefresher.java │ │ ├── model │ │ ├── Importance.java │ │ ├── TopicOperation.java │ │ ├── Urgency.java │ │ └── Visibility.java │ │ ├── reponse │ │ ├── SendResponse.java │ │ ├── TopicListResponse.java │ │ └── TopicSendResponse.java │ │ ├── util │ │ ├── CollectionUtils.java │ │ ├── IgnoreSSLUtils.java │ │ ├── InitAppUtils.java │ │ ├── ResponceCodeProcesser.java │ │ └── ValidatorUtils.java │ │ └── webpush │ │ ├── WebActions.java │ │ ├── WebHmsOptions.java │ │ ├── WebNotification.java │ │ └── WebpushHeaders.java │ └── resources │ └── url.properties └── test └── .gitignore /.github/ISSUE_TEMPLATE/issue-with-the-sample-code.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Issue with the sample code 3 | about: Are you having issues when running the code in this repo? 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Description** 11 | Description of what the issue is about 12 | 13 | **Expected behavior** 14 | What you expected to happen? 15 | 16 | **Current behavior** 17 | What actually happened? 18 | 19 | **Screenshots** 20 | If applicable, add screenshots to help explain your issue 21 | 22 | **Logs** 23 | Post logs here or paste them to [Ghostbin](https://ghostbin.co) and insert the link here. 24 | 25 | **Environment** 26 | - Platform: [e.g. native Android/Cordova/Flutter/…] 27 | - Architecture: [arm-v7a, arm-v7a-neon, arm64-v8a, x86, x86_64, armv7, armv7s, arm64, i386, x86_64] 28 | - OS Version (if applicable) [e.g. Android 11] 29 | - Source branch (if applicable) [e.g. master, dev-v2.x] 30 | - Android Studio version (if applicable) [e.g. 4.1] 31 | - Android NDK version (if applicable) [e.g. 16b, 17c] 32 | 33 | **Other** 34 | Add any other context about the problem here 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | target 3 | 4 | 5 | -------------------------------------------------------------------------------- /3rd-party/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | target 3 | 4 | 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | 3 | Version 2.0, January 2004 4 | 5 | http://www.apache.org/licenses/ 6 | 7 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 8 | 9 | 1. Definitions. 10 | 11 | "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 16 | 17 | "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. 18 | 19 | "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. 20 | 21 | "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. 22 | 23 | "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). 24 | 25 | "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. 26 | 27 | "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." 28 | 29 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 30 | 31 | 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 32 | 33 | 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 34 | 35 | 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 36 | 37 | You must give any other recipients of the Work or Derivative Works a copy of this License; and 38 | You must cause any modified files to carry prominent notices stating that You changed the files; and 39 | You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 40 | If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. 41 | 42 | You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 43 | 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 44 | 45 | 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 46 | 47 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 48 | 49 | 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 50 | 51 | 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. 52 | 53 | END OF TERMS AND CONDITIONS -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HMS Core Push Kit Sample Code (Java) 2 | English | [中文](README_ZH.md) 3 | 4 | ## Contents 5 | 6 | * [Introduction](#Introduction) 7 | * [Environment Requirements](#Environment-Requirements) 8 | * [Installation](#Installation) 9 | * [Configuration](#Configuration) 10 | * [Sample Code](#Sample-Code) 11 | * [Technical Support](#technical-support) 12 | * [License](#License) 13 | 14 | 15 | ## Introduction 16 | 17 | The sample code for Java encapsulates the server-side APIs of Push Kit, for your reference or direct use. 18 | 19 | The following table describes packages of Java sample code. 20 | | Package| Description| 21 | | ---- | ---- | 22 | | examples| Sample code packages.| 23 | | messaging| Package where Push Kit server APIs are encapsulated.| 24 | 25 | ## Environment Requirements 26 | 27 | JDK 8.0 or later is recommended. 28 | 29 | ## Configuration 30 | 31 | Set the following parameters. 32 | 33 | | Parameter| Description| 34 | | ---- | ---- | 35 | | appid| App ID, which is obtained from the app information.| 36 | | appsecret | App secret, which is obtained from the app information.| 37 | | token_server | URL for Huawei OAuth 2.0 to obtain a token. For details, please refer to [OAuth 2.0-based Authentication](https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/oauth2-0000001212610981?ha_source=hms1). | 38 | | push_open_url | Access address of Push Kit. For details, please refer to [Downlink Message Sending](https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/android-server-dev-0000001050040110?ha_source=hms1). | 39 | 40 | ## Sample Code 41 | 42 | #### 1. Send an Android data message. 43 | Code location: [examples/SendDataMessage.java](src/main/java/com/huawei/push/examples/SendDataMessage.java) 44 | 45 | #### 2. Send an Android notification message. 46 | Code location: [examples/SendNotifyMessage.java](src/main/java/com/huawei/push/examples/SendNotifyMessage.java) 47 | 48 | #### 3. Send a message by topic. 49 | Code location: [examples/SendTopicMessage.java](src/main/java/com/huawei/push/examples/SendTopicMessage.java) 50 | 51 | #### 4. Send a message by conditions. 52 | Code location: [examples/SendConditionMessage.java](src/main/java/com/huawei/push/examples/SendConditionMessage.java) 53 | 54 | #### 5. Send a message to a Huawei quick app. 55 | Code location: [examples/SendInstanceAppMessage.java](src/main/java/com/huawei/push/examples/SendInstanceAppMessage.java) 56 | 57 | #### 6. Send a message through the WebPush agent. 58 | Code location: [examples/SendWebpushMessage.java](src/main/java/com/huawei/push/examples/SendWebpushMessage.java) 59 | 60 | #### 7. Send a message through the APNs agent. 61 | Code location: [examples/SendApnsMessage.java](src/main/java/com/huawei/push/examples/SendApnsMessage.java) 62 | 63 | #### 8. Send a test message. 64 | Code location: [examples/SendTestMessage.java](src/main/java/com/huawei/push/examples/SendTestMessage.java) 65 | 66 | ## Technical Support 67 | You can visit the [Reddit community](https://www.reddit.com/r/HuaweiDevelopers/) to obtain the latest information about HMS Core and communicate with other developers. 68 | 69 | If you have any questions about the sample code, try the following: 70 | - Visit [Stack Overflow](https://stackoverflow.com/questions/tagged/huawei-mobile-services?tab=Votes), submit your questions, and tag them with `huawei-mobile-services`. Huawei experts will answer your questions. 71 | - Visit the HMS Core section in the [HUAWEI Developer Forum](https://forums.developer.huawei.com/forumPortal/en/home?fid=0101187876626530001?ha_source=hms1) and communicate with other developers. 72 | 73 | If you encounter any issues when using the sample code, submit your [issues](https://github.com/HMS-Core/hms-push-serverdemo-java/issues) or submit a [pull request](https://github.com/HMS-Core/hms-push-serverdemo-java/pulls). 74 | 75 | ## License 76 | The sample code is licensed under [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0). 77 | -------------------------------------------------------------------------------- /README_ZH.md: -------------------------------------------------------------------------------- 1 | # 华为推送服务服务端Java示例代码 2 | [English](README.md) | 中文 3 | 4 | ## 目录 5 | 6 | * [简介](#简介) 7 | * [环境要求](#环境要求) 8 | * [安装](#安装) 9 | * [配置](#配置) 10 | * [示例代码](#示例代码) 11 | * [技术支持](#技术支持) 12 | * [授权许可](#授权许可) 13 | 14 | 15 | ## 简介 16 | 17 | Java示例代码对华为推送服务(HUAWEI Push Kit)服务端接口进行封装,供您参考使用。 18 | 19 | 示例代码目录结构如下: 20 | | 包名 | 说明 | 21 | | ---- | ---- | 22 | | examples | 示例代码包 | 23 | | messaging | 服务端接口封装包 | 24 | 25 | ## 环境要求 26 | 27 | 推荐使用JDK 8.0及以上版本。 28 | 29 | ## 配置 30 | 31 | 参数说明: 32 | 33 | | 参数 | 说明 | 34 | | ---- | ---- | 35 | | appid | 应用ID,从应用信息中获取 | 36 | | appsecret | 应用访问密钥,从应用信息中获取 | 37 | | token_server | 华为OAuth 2.0获取token的地址。详情请参见[基于OAuth 2.0开放鉴权-客户端模式](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/oauth2-0000001212610981)。| 38 | | push_open_url | 推送服务的访问地址。详情请参见[推送服务-下行消息](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/android-server-dev-0000001050040110?ha_source=hms1)。| 39 | 40 | ## 示例代码 41 | 42 | #### 1. 发送Android透传消息 43 | 代码位置:[examples/SendDataMessage.java](src/main/java/com/huawei/push/examples/SendDataMessage.java) 44 | 45 | #### 2. 发送Android通知栏消息 46 | 代码位置:[examples/SendNotifyMessage.java](src/main/java/com/huawei/push/examples/SendNotifyMessage.java) 47 | 48 | #### 3. 基于主题发送消息 49 | 代码位置:[examples/SendTopicMessage.java](src/main/java/com/huawei/push/examples/SendTopicMessage.java) 50 | 51 | #### 4. 基于条件发送消息 52 | 代码位置:[examples/SendConditionMessage.java](src/main/java/com/huawei/push/examples/SendConditionMessage.java) 53 | 54 | #### 5. 向华为快应用发送消息 55 | 代码位置:[examples/SendInstanceAppMessage.java](src/main/java/com/huawei/push/examples/SendInstanceAppMessage.java) 56 | 57 | #### 6. 基于WebPush代理发送消息 58 | 代码位置:[examples/SendWebpushMessage.java](src/main/java/com/huawei/push/examples/SendWebpushMessage.java) 59 | 60 | #### 7. 基于APNs代理发送消息 61 | 代码位置:[examples/SendApnsMessage.java](src/main/java/com/huawei/push/examples/SendApnsMessage.java) 62 | 63 | #### 8. 发送测试消息 64 | 代码位置:[examples/SendTestMessage.java](src/main/java/com/huawei/push/examples/SendTestMessage.java) 65 | 66 | ## 技术支持 67 | 如果您对HMS Core还处于评估阶段,可在[Reddit社区](https://www.reddit.com/r/HuaweiDevelopers/)获取关于HMS Core的最新讯息,并与其他开发者交流见解。 68 | 69 | 如果您对使用HMS示例代码有疑问,请尝试: 70 | - 开发过程遇到问题上[Stack Overflow](https://stackoverflow.com/questions/tagged/huawei-mobile-services?tab=Votes),在`huawei-mobile-services`标签下提问,有华为研发专家在线一对一解决您的问题。 71 | - 到[华为开发者论坛](https://developer.huawei.com/consumer/cn/forum/blockdisplay?fid=18?ha_source=hms1) HMS Core板块与其他开发者进行交流。 72 | 73 | 如果您在尝试示例代码中遇到问题,请向仓库提交[issue](https://github.com/HMS-Core/hms-push-serverdemo-java/issues),也欢迎您提交[Pull Request](https://github.com/HMS-Core/hms-push-serverdemo-java/pulls)。 74 | 75 | ## 授权许可 76 | 华为推送服务Java示例代码经过 [Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0)授权许可。 77 | -------------------------------------------------------------------------------- /Third Party Open Source Software Notice.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HMS-Core/hms-push-serverdemo-java/63d96aeb9111c1f3759c669df8a7bf9fb86aa6bd/Third Party Open Source Software Notice.docx -------------------------------------------------------------------------------- /build/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | target 3 | 4 | 5 | -------------------------------------------------------------------------------- /dist/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | target 3 | 4 | 5 | -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | target 3 | 4 | 5 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.huawei.pushplatform 8 | push.java.sample 9 | 1.0 10 | 11 | 12 | 13 | 14 | org.apache.commons 15 | commons-lang3 16 | 3.9 17 | 18 | 19 | com.google.guava 20 | guava 21 | 26.0-jre 22 | 23 | 24 | org.slf4j 25 | slf4j-api 26 | 1.7.26 27 | 28 | 29 | com.alibaba 30 | fastjson 31 | 1.2.62 32 | 33 | 34 | org.apache.httpcomponents 35 | httpclient 36 | 4.5.7 37 | 38 | 39 | 40 | 41 | junit 42 | junit 43 | 4.12 44 | test 45 | 46 | 47 | org.slf4j 48 | slf4j-nop 49 | 1.7.2 50 | test 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | org.apache.maven.plugins 59 | maven-compiler-plugin 60 | 3.5.1 61 | 62 | 1.8 63 | 1.8 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/android/BadgeNotification.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.android; 17 | 18 | import com.alibaba.fastjson.annotation.JSONField; 19 | import com.huawei.push.util.ValidatorUtils; 20 | 21 | public class BadgeNotification { 22 | @JSONField(name = "add_num") 23 | private Integer addNum; 24 | 25 | @JSONField(name = "class") 26 | private String badgeClass; 27 | 28 | @JSONField(name = "set_num") 29 | private Integer setNum; 30 | 31 | public Integer getAddNum() { 32 | return addNum; 33 | } 34 | 35 | public String getBadgeClass() { 36 | return badgeClass; 37 | } 38 | 39 | public Integer getSetNum() { 40 | return setNum; 41 | } 42 | 43 | public BadgeNotification(Integer addNum, String badgeClass) { 44 | this.addNum = addNum; 45 | this.badgeClass = badgeClass; 46 | } 47 | 48 | public BadgeNotification(Builder builder) { 49 | this.addNum = builder.addNum; 50 | this.badgeClass = builder.badgeClass; 51 | this.setNum = builder.setNum; 52 | } 53 | 54 | public void check() { 55 | if (this.addNum != null) { 56 | ValidatorUtils.checkArgument(this.addNum.intValue() > 0 && this.addNum.intValue() < 100, "add_num should locate between 0 and 100"); 57 | } 58 | if (this.setNum != null) { 59 | ValidatorUtils.checkArgument(this.setNum.intValue() >= 0 && this.setNum.intValue() < 100, "set_num should locate between 0 and 100"); 60 | } 61 | } 62 | 63 | /** 64 | * builder 65 | */ 66 | public static Builder builder() { 67 | return new Builder(); 68 | } 69 | 70 | public static class Builder { 71 | private Integer addNum; 72 | 73 | private String badgeClass; 74 | 75 | private Integer setNum; 76 | 77 | public Builder setAddNum(Integer addNum) { 78 | this.addNum = addNum; 79 | return this; 80 | } 81 | 82 | public Builder setSetNum(Integer setNum) { 83 | this.setNum = setNum; 84 | return this; 85 | } 86 | 87 | public Builder setBadgeClass(String badgeClass) { 88 | this.badgeClass = badgeClass; 89 | return this; 90 | } 91 | 92 | public BadgeNotification build() { 93 | return new BadgeNotification(this); 94 | } 95 | } 96 | 97 | 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/android/Button.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Huawei Technologies Co., Ltd. 2019-2029. All rights reserved. 3 | */ 4 | 5 | package com.huawei.push.android; 6 | 7 | import com.alibaba.fastjson.annotation.JSONField; 8 | import com.huawei.push.util.ValidatorUtils; 9 | 10 | import org.apache.commons.lang3.StringUtils; 11 | 12 | /** 13 | * 功能描述 14 | * 15 | * @author l00282963 16 | * @since 2020-01-19 17 | */ 18 | public class Button { 19 | @JSONField(name = "name") 20 | private String name; 21 | 22 | @JSONField(name = "action_type") 23 | private Integer actionType; 24 | 25 | @JSONField(name = "intent_type") 26 | private Integer intentType; 27 | 28 | @JSONField(name = "intent") 29 | private String intent; 30 | 31 | @JSONField(name = "data") 32 | private String data; 33 | 34 | public String getName() { 35 | return name; 36 | } 37 | 38 | public Integer getActionType() { 39 | return actionType; 40 | } 41 | 42 | public Integer getIntentType() { 43 | return intentType; 44 | } 45 | 46 | public String getIntent() { 47 | return intent; 48 | } 49 | 50 | public String getData() { 51 | return data; 52 | } 53 | 54 | 55 | public Button(Builder builder) { 56 | this.name = builder.name; 57 | this.actionType = builder.actionType; 58 | this.intentType = builder.intentType; 59 | this.intent = builder.intent; 60 | this.data = builder.data; 61 | } 62 | 63 | public void check() { 64 | if (this.actionType != null && this.actionType == 4) { 65 | ValidatorUtils.checkArgument(StringUtils.isNotEmpty(this.data), "data is needed when actionType is 4"); 66 | } 67 | } 68 | 69 | /** 70 | * builder 71 | */ 72 | public static Builder builder() { 73 | return new Builder(); 74 | } 75 | 76 | public static class Builder { 77 | @JSONField(name = "name") 78 | private String name; 79 | 80 | @JSONField(name = "actionType") 81 | private Integer actionType; 82 | 83 | @JSONField(name = "intentType") 84 | private Integer intentType; 85 | 86 | @JSONField(name = "intent") 87 | private String intent; 88 | 89 | @JSONField(name = "data") 90 | private String data; 91 | 92 | public Builder setName(String name) { 93 | this.name = name; 94 | return this; 95 | } 96 | 97 | public Builder setActionType(Integer actionType) { 98 | this.actionType = actionType; 99 | return this; 100 | } 101 | 102 | public Builder setIntentType(Integer intentType) { 103 | this.intentType = intentType; 104 | return this; 105 | } 106 | 107 | public Builder setIntent(String intent) { 108 | this.intent = intent; 109 | return this; 110 | } 111 | 112 | public Builder setData(String data) { 113 | this.data = data; 114 | return this; 115 | } 116 | 117 | public Button build() { 118 | return new Button(this); 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/android/ClickAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.android; 17 | 18 | import com.alibaba.fastjson.annotation.JSONField; 19 | import com.huawei.push.util.ValidatorUtils; 20 | 21 | import org.apache.commons.lang3.StringUtils; 22 | 23 | public class ClickAction { 24 | private static final String PATTERN = "^https.*"; 25 | 26 | @JSONField(name = "type") 27 | private Integer type; 28 | 29 | @JSONField(name = "intent") 30 | private String intent; 31 | 32 | @JSONField(name = "url") 33 | private String url; 34 | 35 | @JSONField(name = "rich_resource") 36 | private String richResource; 37 | 38 | @JSONField(name = "action") 39 | private String action; 40 | 41 | private ClickAction(Builder builder) { 42 | this.type = builder.type; 43 | switch (this.type) { 44 | case 1: 45 | this.intent = builder.intent; 46 | this.action = builder.action; 47 | break; 48 | case 2: 49 | this.url = builder.url; 50 | break; 51 | case 4: 52 | this.richResource = builder.richResource; 53 | break; 54 | } 55 | } 56 | 57 | /** 58 | * check clickAction's parameters 59 | */ 60 | public void check() { 61 | boolean isTrue = this.type == 1 || 62 | this.type == 2 || 63 | this.type == 3 || 64 | this.type == 4; 65 | ValidatorUtils.checkArgument(isTrue, "click type should be one of 1: customize action, 2: open url, 3: open app, 4: open rich media"); 66 | 67 | switch (this.type) { 68 | case 1: 69 | ValidatorUtils.checkArgument(StringUtils.isNotEmpty(this.intent) || StringUtils.isNotEmpty(this.action), "intent or action is required when click type=1"); 70 | break; 71 | case 2: 72 | ValidatorUtils.checkArgument(StringUtils.isNotEmpty(this.url), "url is required when click type=2"); 73 | ValidatorUtils.checkArgument(this.url.matches(PATTERN), "url must start with https"); 74 | break; 75 | case 4: 76 | ValidatorUtils.checkArgument(StringUtils.isNotEmpty(this.richResource), "richResource is required when click type=4"); 77 | ValidatorUtils.checkArgument(this.richResource.matches(PATTERN), "richResource must start with https"); 78 | break; 79 | } 80 | } 81 | 82 | /** 83 | * getter 84 | */ 85 | public int getType() { 86 | return type; 87 | } 88 | 89 | public String getIntent() { 90 | return intent; 91 | } 92 | 93 | public String getUrl() { 94 | return url; 95 | } 96 | 97 | public String getRichResource() { 98 | return richResource; 99 | } 100 | 101 | public String getAction() { 102 | return action; 103 | } 104 | 105 | /** 106 | * builder 107 | */ 108 | public static Builder builder() { 109 | return new Builder(); 110 | } 111 | 112 | public static class Builder { 113 | private Integer type; 114 | private String intent; 115 | private String url; 116 | private String richResource; 117 | private String action; 118 | 119 | private Builder() { 120 | } 121 | 122 | public Builder setType(Integer type) { 123 | this.type = type; 124 | return this; 125 | } 126 | 127 | public Builder setIntent(String intent) { 128 | this.intent = intent; 129 | return this; 130 | } 131 | 132 | public Builder setUrl(String url) { 133 | this.url = url; 134 | return this; 135 | } 136 | 137 | public Builder setRichResource(String richResource) { 138 | this.richResource = richResource; 139 | return this; 140 | } 141 | 142 | public Builder setAction(String action) { 143 | this.action = action; 144 | return this; 145 | } 146 | 147 | public ClickAction build() { 148 | return new ClickAction(this); 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/android/Color.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.android; 17 | 18 | import com.alibaba.fastjson.annotation.JSONField; 19 | import com.huawei.push.util.ValidatorUtils; 20 | 21 | public class Color { 22 | private final float zero = -0.000001f; 23 | 24 | private final float one = 1.000001f; 25 | 26 | @JSONField(name = "alpha") 27 | private Float alpha = new Float(1.0); 28 | 29 | @JSONField(name = "red") 30 | private Float red = new Float(0.0); 31 | 32 | @JSONField(name = "green") 33 | private Float green = new Float(0.0); 34 | 35 | @JSONField(name = "blue") 36 | private Float blue = new Float(0.0); 37 | 38 | public Color(Builder builder) { 39 | this.alpha = builder.alpha; 40 | this.red = builder.red; 41 | this.green = builder.green; 42 | this.blue = builder.blue; 43 | } 44 | 45 | public double getAlpha() { 46 | return alpha; 47 | } 48 | 49 | public Float getRed() { 50 | return red; 51 | } 52 | 53 | public Float getGreen() { 54 | return green; 55 | } 56 | 57 | public Float getBlue() { 58 | return blue; 59 | } 60 | 61 | public void check() { 62 | ValidatorUtils.checkArgument(this.alpha > zero && this.alpha < one, "Alpha shoube locate between [0,1]"); 63 | ValidatorUtils.checkArgument(this.red > zero && this.red < one, "Red shoube locate between [0,1]"); 64 | ValidatorUtils.checkArgument(this.green > zero && this.green < one, "Green shoube locate between [0,1]"); 65 | ValidatorUtils.checkArgument(this.blue > zero && this.blue < one, "Blue shoube locate between [0,1]"); 66 | } 67 | 68 | /** 69 | * builder 70 | */ 71 | public static Builder builder() { 72 | return new Builder(); 73 | } 74 | 75 | public static class Builder { 76 | private Float alpha = new Float(1.0); 77 | private Float red = new Float(0.0); 78 | private Float green = new Float(0.0); 79 | private Float blue = new Float(0.0); 80 | 81 | public Builder setAlpha(Float alpha) { 82 | this.alpha = alpha; 83 | return this; 84 | } 85 | 86 | public Builder setRed(Float red) { 87 | this.red = red; 88 | return this; 89 | } 90 | 91 | public Builder setGreen(Float green) { 92 | this.green = green; 93 | return this; 94 | } 95 | 96 | public Builder setBlue(Float blue) { 97 | this.blue = blue; 98 | return this; 99 | } 100 | 101 | public Color build() { 102 | return new Color(this); 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/android/LightSettings.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.android; 17 | 18 | import com.alibaba.fastjson.annotation.JSONField; 19 | import com.huawei.push.util.ValidatorUtils; 20 | 21 | public class LightSettings { 22 | private static final String LIGTH_DURATION_PATTERN = "\\d+|\\d+[sS]|\\d+.\\d{1,9}|\\d+.\\d{1,9}[sS]"; 23 | 24 | @JSONField(name = "color") 25 | private Color color; 26 | 27 | @JSONField(name = "light_on_duration") 28 | private String lightOnDuration; 29 | 30 | @JSONField(name = "light_off_duration") 31 | private String lightOffDuration; 32 | 33 | public LightSettings(Builder builder) { 34 | this.color = builder.color; 35 | this.lightOnDuration = builder.lightOnDuration; 36 | this.lightOffDuration = builder.lightOffDuration; 37 | } 38 | 39 | public Color getColor() { 40 | return color; 41 | } 42 | 43 | public String getLightOnDuration() { 44 | return lightOnDuration; 45 | } 46 | 47 | public String getLightOffDuration() { 48 | return lightOffDuration; 49 | } 50 | 51 | /** 52 | * 参数校验 53 | */ 54 | public void check() { 55 | ValidatorUtils.checkArgument(this.color != null, "color must be selected when light_settings is set"); 56 | 57 | if (this.color != null) { 58 | this.color.check(); 59 | } 60 | 61 | ValidatorUtils.checkArgument(this.lightOnDuration != null, "light_on_duration must be selected when light_settings is set"); 62 | 63 | ValidatorUtils.checkArgument(this.lightOffDuration != null, "light_off_duration must be selected when light_settings is set"); 64 | 65 | ValidatorUtils.checkArgument(this.lightOnDuration.matches(LIGTH_DURATION_PATTERN), "light_on_duration format is wrong"); 66 | 67 | ValidatorUtils.checkArgument(this.lightOffDuration.matches(LIGTH_DURATION_PATTERN), "light_off_duration format is wrong"); 68 | } 69 | 70 | /** 71 | * builder 72 | */ 73 | public static Builder builder() { 74 | return new Builder(); 75 | } 76 | 77 | public static class Builder { 78 | private Color color; 79 | private String lightOnDuration; 80 | private String lightOffDuration; 81 | 82 | public Builder setColor(Color color) { 83 | this.color = color; 84 | return this; 85 | } 86 | 87 | public Builder setLightOnDuration(String lightOnDuration) { 88 | this.lightOnDuration = lightOnDuration; 89 | return this; 90 | } 91 | 92 | public Builder setLightOffDuration(String lightOffDuration) { 93 | this.lightOffDuration = lightOffDuration; 94 | return this; 95 | } 96 | 97 | public LightSettings build() { 98 | return new LightSettings(this); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/apns/Alert.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.apns; 17 | 18 | import com.alibaba.fastjson.annotation.JSONField; 19 | import com.huawei.push.util.CollectionUtils; 20 | import com.huawei.push.util.ValidatorUtils; 21 | 22 | import org.apache.commons.lang3.StringUtils; 23 | 24 | import java.util.ArrayList; 25 | import java.util.List; 26 | 27 | public class Alert { 28 | @JSONField(name = "title") 29 | private String title; 30 | 31 | @JSONField(name = "body") 32 | private String body; 33 | 34 | @JSONField(name = "title-loc-key") 35 | private String titleLocKey; 36 | 37 | @JSONField(name = "title-loc-args") 38 | private List titleLocArgs = new ArrayList(); 39 | 40 | @JSONField(name = "action-loc-key") 41 | private String actionLocKey; 42 | 43 | @JSONField(name = "loc-key") 44 | private String locKey; 45 | 46 | @JSONField(name = "loc-args") 47 | private List locArgs = new ArrayList(); 48 | 49 | @JSONField(name = "launch-image") 50 | private String launchImage; 51 | 52 | public String getTitle() { 53 | return title; 54 | } 55 | 56 | public String getBody() { 57 | return body; 58 | } 59 | 60 | public String getTitleLocKey() { 61 | return titleLocKey; 62 | } 63 | 64 | public List getTitleLocArgs() { 65 | return titleLocArgs; 66 | } 67 | 68 | public String getActionLocKey() { 69 | return actionLocKey; 70 | } 71 | 72 | public String getLocKey() { 73 | return locKey; 74 | } 75 | 76 | public List getLocArgs() { 77 | return locArgs; 78 | } 79 | 80 | public String getLaunchImage() { 81 | return launchImage; 82 | } 83 | 84 | private Alert(Builder builder) { 85 | this.title = builder.title; 86 | this.body = builder.body; 87 | this.titleLocKey = builder.titleLocKey; 88 | if (!CollectionUtils.isEmpty(builder.titleLocArgs)) { 89 | this.titleLocArgs.addAll(builder.titleLocArgs); 90 | } else { 91 | this.titleLocArgs = null; 92 | } 93 | this.actionLocKey = builder.actionLocKey; 94 | this.locKey = builder.locKey; 95 | if (!CollectionUtils.isEmpty(builder.locArgs)) { 96 | this.locArgs.addAll(builder.locArgs); 97 | } else { 98 | this.locArgs = null; 99 | } 100 | this.launchImage = builder.launchImage; 101 | } 102 | 103 | public void check() { 104 | if (!CollectionUtils.isEmpty(this.locArgs)) { 105 | ValidatorUtils.checkArgument(StringUtils.isNotEmpty(this.locKey), "locKey is required when specifying locArgs"); 106 | } 107 | if (!CollectionUtils.isEmpty(this.titleLocArgs)) { 108 | ValidatorUtils.checkArgument(StringUtils.isNotEmpty(this.titleLocKey), "titleLocKey is required when specifying titleLocArgs"); 109 | } 110 | } 111 | 112 | /** 113 | * builder 114 | * 115 | * @return 116 | */ 117 | public static Builder builder() { 118 | return new Builder(); 119 | } 120 | 121 | public static class Builder { 122 | private String title; 123 | private String body; 124 | private String titleLocKey; 125 | private List titleLocArgs = new ArrayList(); 126 | private String actionLocKey; 127 | private String locKey; 128 | private List locArgs = new ArrayList(); 129 | private String launchImage; 130 | 131 | public Builder setTitle(String title) { 132 | this.title = title; 133 | return this; 134 | 135 | } 136 | 137 | public Builder setBody(String body) { 138 | this.body = body; 139 | return this; 140 | } 141 | 142 | public Builder setTitleLocKey(String titleLocKey) { 143 | this.titleLocKey = titleLocKey; 144 | return this; 145 | } 146 | 147 | public Builder setAddAllTitleLocArgs(List titleLocArgs) { 148 | this.titleLocArgs.addAll(titleLocArgs); 149 | return this; 150 | } 151 | 152 | public Builder setAddTitleLocArg(String titleLocArg) { 153 | this.titleLocArgs.add(titleLocArg); 154 | return this; 155 | } 156 | 157 | public Builder setActionLocKey(String actionLocKey) { 158 | this.actionLocKey = actionLocKey; 159 | return this; 160 | } 161 | 162 | public Builder setLocKey(String locKey) { 163 | this.locKey = locKey; 164 | return this; 165 | } 166 | 167 | public Builder addAllLocArgs(List locArgs) { 168 | this.locArgs.addAll(locArgs); 169 | return this; 170 | } 171 | 172 | public Builder addLocArg(String locArg) { 173 | this.locArgs.add(locArg); 174 | return this; 175 | } 176 | 177 | public Builder setLaunchImage(String launchImage) { 178 | this.launchImage = launchImage; 179 | return this; 180 | } 181 | 182 | public Alert build() { 183 | return new Alert(this); 184 | } 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/apns/ApnsHeaders.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.apns; 17 | 18 | import com.alibaba.fastjson.annotation.JSONField; 19 | import com.huawei.push.util.ValidatorUtils; 20 | 21 | public class ApnsHeaders { 22 | private static final String AUTHORIZATION_PATTERN = "^bearer*"; 23 | 24 | private static final String APN_ID_PATTERN = "[0-9a-z]{8}(-[0-9a-z]{4}){3}-[0-9a-z]{12}"; 25 | 26 | private static final int SEND_IMMEDIATELY = 10; 27 | 28 | private static final int SEND_BY_GROUP = 5; 29 | 30 | @JSONField(name = "authorization") 31 | private String authorization; 32 | 33 | @JSONField(name = "apns-id") 34 | private String apnsId; 35 | 36 | @JSONField(name = "apns-expiration") 37 | private Long apnsExpiration; 38 | 39 | @JSONField(name = "apns-priority") 40 | private String apnsPriority; 41 | 42 | @JSONField(name = "apns-topic") 43 | private String apnsTopic; 44 | 45 | @JSONField(name = "apns-collapse-id") 46 | private String apnsCollapseId; 47 | 48 | public String getAuthorization() { 49 | return authorization; 50 | } 51 | 52 | public String getApnsId() { 53 | return apnsId; 54 | } 55 | 56 | public Long getApnsExpiration() { 57 | return apnsExpiration; 58 | } 59 | 60 | public String getApnsPriority() { 61 | return apnsPriority; 62 | } 63 | 64 | public String getApnsTopic() { 65 | return apnsTopic; 66 | } 67 | 68 | public String getApnsCollapseId() { 69 | return apnsCollapseId; 70 | } 71 | 72 | public void check() { 73 | if (this.authorization != null) { 74 | ValidatorUtils.checkArgument(this.authorization.matches(AUTHORIZATION_PATTERN), "authorization must start with bearer"); 75 | } 76 | if (this.apnsId != null) { 77 | ValidatorUtils.checkArgument(this.apnsId.matches(APN_ID_PATTERN), "apns-id format error"); 78 | } 79 | if (this.apnsPriority != null) { 80 | ValidatorUtils.checkArgument(Integer.parseInt(this.apnsPriority) == SEND_BY_GROUP || 81 | Integer.parseInt(this.apnsPriority) == SEND_IMMEDIATELY, "apns-priority should be SEND_BY_GROUP:5 or SEND_IMMEDIATELY:10"); 82 | } 83 | if (this.apnsCollapseId != null) { 84 | ValidatorUtils.checkArgument(this.apnsCollapseId.getBytes().length < 64, "Number of apnsCollapseId bytes should be less than 64"); 85 | } 86 | } 87 | 88 | private ApnsHeaders(Builder builder) { 89 | this.authorization = builder.authorization; 90 | this.apnsId = builder.apnsId; 91 | this.apnsExpiration = builder.apnsExpiration; 92 | this.apnsPriority = builder.apnsPriority; 93 | this.apnsTopic = builder.apnsTopic; 94 | this.apnsCollapseId = builder.apnsCollapseId; 95 | } 96 | 97 | /** 98 | * builder 99 | */ 100 | public static Builder builder() { 101 | return new Builder(); 102 | } 103 | 104 | public static class Builder { 105 | private String authorization; 106 | private String apnsId; 107 | private Long apnsExpiration; 108 | private String apnsPriority; 109 | private String apnsTopic; 110 | private String apnsCollapseId; 111 | 112 | public Builder setAuthorization(String authorization) { 113 | this.authorization = authorization; 114 | return this; 115 | } 116 | 117 | public Builder setApnsId(String apnsId) { 118 | this.apnsId = apnsId; 119 | return this; 120 | } 121 | 122 | public Builder setApnsExpiration(Long apnsExpiration) { 123 | this.apnsExpiration = apnsExpiration; 124 | return this; 125 | } 126 | 127 | public Builder setApnsPriority(String apnsPriority) { 128 | this.apnsPriority = apnsPriority; 129 | return this; 130 | } 131 | 132 | public Builder setApnsTopic(String apnsTopic) { 133 | this.apnsTopic = apnsTopic; 134 | return this; 135 | } 136 | 137 | public Builder setApnsCollapseId(String apnsCollapseId) { 138 | this.apnsCollapseId = apnsCollapseId; 139 | return this; 140 | } 141 | 142 | public ApnsHeaders build() { 143 | return new ApnsHeaders(this); 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/apns/ApnsHmsOptions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.apns; 17 | 18 | import com.alibaba.fastjson.annotation.JSONField; 19 | import com.huawei.push.util.ValidatorUtils; 20 | 21 | public class ApnsHmsOptions { 22 | private static final int TEST_USER = 1; 23 | private static final int FORMAL_USER = 2; 24 | private static final int VOIP_USER = 3; 25 | 26 | @JSONField(name = "target_user_type") 27 | private Integer targetUserType; 28 | 29 | public Integer getTargetUserType() { 30 | return targetUserType; 31 | } 32 | 33 | private ApnsHmsOptions(Builder builder){ 34 | this.targetUserType = builder.targetUserType; 35 | } 36 | 37 | public void check(){ 38 | if (targetUserType != null) { 39 | ValidatorUtils.checkArgument(this.targetUserType.intValue() == TEST_USER 40 | || this.targetUserType.intValue() == FORMAL_USER 41 | || this.targetUserType.intValue() == VOIP_USER, 42 | "targetUserType should be [TEST_USER: 1, FORMAL_USER: 2, VOIP_USER: 3]"); 43 | } 44 | } 45 | 46 | /** 47 | * builder 48 | */ 49 | public static Builder builder() { 50 | return new Builder(); 51 | } 52 | 53 | public static class Builder { 54 | private Integer targetUserType; 55 | 56 | public Builder setTargetUserType(Integer targetUserType) { 57 | this.targetUserType = targetUserType; 58 | return this; 59 | } 60 | 61 | public ApnsHmsOptions build(){ 62 | return new ApnsHmsOptions(this); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/apns/Aps.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.apns; 17 | 18 | import com.alibaba.fastjson.annotation.JSONField; 19 | import com.huawei.push.util.ValidatorUtils; 20 | 21 | public class Aps { 22 | @JSONField(name = "alert") 23 | private Object alert; 24 | 25 | @JSONField(name = "badge") 26 | private Integer badge; 27 | 28 | @JSONField(name = "sound") 29 | private String sound; 30 | 31 | @JSONField(name = "content-available") 32 | private Integer contentAvailable; 33 | 34 | @JSONField(name = "category") 35 | private String category; 36 | 37 | @JSONField(name = "thread-id") 38 | private String threadId; 39 | 40 | public Object getAlert() { 41 | return alert; 42 | } 43 | 44 | public Integer getBadge() { 45 | return badge; 46 | } 47 | 48 | public String getSound() { 49 | return sound; 50 | } 51 | 52 | public Integer getContentAvailable() { 53 | return contentAvailable; 54 | } 55 | 56 | public String getCategory() { 57 | return category; 58 | } 59 | 60 | public String getThreadId() { 61 | return threadId; 62 | } 63 | 64 | public void check() { 65 | if (this.alert != null) { 66 | if(this.alert instanceof Alert){ 67 | ((Alert) this.alert).check(); 68 | }else{ 69 | ValidatorUtils.checkArgument((this.alert instanceof String), "Alter should be Dictionary or String"); 70 | } 71 | } 72 | } 73 | 74 | private Aps(Builder builder) { 75 | this.alert = builder.alert; 76 | this.badge = builder.badge; 77 | this.sound = builder.sound; 78 | this.contentAvailable = builder.contentAvailable; 79 | this.category = builder.category; 80 | this.threadId = builder.threadId; 81 | } 82 | 83 | public static Builder builder() { 84 | return new Builder(); 85 | } 86 | 87 | public static class Builder { 88 | private Object alert; 89 | private Integer badge; 90 | private String sound; 91 | private Integer contentAvailable; 92 | private String category; 93 | private String threadId; 94 | 95 | public Builder setAlert(Object alert) { 96 | this.alert = alert; 97 | return this; 98 | } 99 | 100 | public Builder setBadge(Integer badge) { 101 | this.badge = badge; 102 | return this; 103 | } 104 | 105 | public Builder setSound(String sound) { 106 | this.sound = sound; 107 | return this; 108 | } 109 | 110 | public Builder setContentAvailable(Integer contentAvailable) { 111 | this.contentAvailable = contentAvailable; 112 | return this; 113 | } 114 | 115 | public Builder setCategory(String category) { 116 | this.category = category; 117 | return this; 118 | } 119 | 120 | public Builder setThreadId(String threadId) { 121 | this.threadId = threadId; 122 | return this; 123 | } 124 | 125 | public Aps build() { 126 | return new Aps(this); 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/examples/SendApnsMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.examples; 17 | 18 | import com.huawei.push.apns.Alert; 19 | import com.huawei.push.apns.ApnsHeaders; 20 | import com.huawei.push.apns.ApnsHmsOptions; 21 | import com.huawei.push.apns.Aps; 22 | import com.huawei.push.exception.HuaweiMesssagingException; 23 | import com.huawei.push.message.ApnsConfig; 24 | import com.huawei.push.message.Message; 25 | import com.huawei.push.messaging.HuaweiApp; 26 | import com.huawei.push.messaging.HuaweiMessaging; 27 | import com.huawei.push.reponse.SendResponse; 28 | import com.huawei.push.util.InitAppUtils; 29 | 30 | public class SendApnsMessage { 31 | /** 32 | * send apns message 33 | * 34 | * @throws HuaweiMesssagingException 35 | */ 36 | public void sendApnsMessage() throws HuaweiMesssagingException { 37 | HuaweiApp app = InitAppUtils.initializeApp(); 38 | HuaweiMessaging huaweiMessaging = HuaweiMessaging.getInstance(app); 39 | 40 | ApnsHeaders apnsHeaders = ApnsHeaders.builder().setApnsId("123e4567-e89b-12d3-a456-426655440000").build(); 41 | 42 | Alert altert = Alert.builder().setTitle("titile") 43 | .setBody("body") 44 | .setLaunchImage("image") 45 | .build(); 46 | 47 | Aps aps = Aps.builder().setAlert(altert) 48 | .setBadge(1) 49 | .setSound("wtewt.mp4") 50 | .setContentAvailable(1) 51 | .setCategory("category") 52 | .setThreadId("id") 53 | .build(); 54 | 55 | ApnsHmsOptions apnsHmsOptions = ApnsHmsOptions.builder().setTargetUserType(1).build(); 56 | 57 | ApnsConfig apns = ApnsConfig.builder().setApnsHeaders(apnsHeaders) 58 | .addPayloadAps(aps) 59 | .addPayload("acme_account", "jane.appleseed@apple.com") 60 | .addPayload("acme_message", "message123456") 61 | .setHmsOptions(apnsHmsOptions) 62 | .build(); 63 | 64 | Message message = Message.builder().setApns(apns) 65 | .addToken("9FDA406A04BDE017A2F53EB9831846FBF5308567DE9A4E986D96512136F72C3D") 66 | .build(); 67 | 68 | SendResponse response = huaweiMessaging.sendMessage(message); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/examples/SendConditionMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.examples; 17 | 18 | import com.alibaba.fastjson.JSONObject; 19 | import com.huawei.push.android.AndroidNotification; 20 | import com.huawei.push.android.BadgeNotification; 21 | import com.huawei.push.android.ClickAction; 22 | import com.huawei.push.android.Color; 23 | import com.huawei.push.android.LightSettings; 24 | import com.huawei.push.exception.HuaweiMesssagingException; 25 | import com.huawei.push.message.AndroidConfig; 26 | import com.huawei.push.message.Message; 27 | import com.huawei.push.message.Notification; 28 | import com.huawei.push.messaging.HuaweiApp; 29 | import com.huawei.push.messaging.HuaweiMessaging; 30 | import com.huawei.push.model.Urgency; 31 | import com.huawei.push.model.Importance; 32 | import com.huawei.push.model.Visibility; 33 | import com.huawei.push.reponse.SendResponse; 34 | import com.huawei.push.util.InitAppUtils; 35 | 36 | public class SendConditionMessage { 37 | /** 38 | * send message to condition 39 | * 40 | * @throws HuaweiMesssagingException 41 | */ 42 | public void sendToCondition() throws HuaweiMesssagingException { 43 | HuaweiApp app = InitAppUtils.initializeApp(); 44 | HuaweiMessaging huaweiMessaging = HuaweiMessaging.getInstance(app); 45 | 46 | Notification notification = Notification.builder().setTitle("send condition message title") 47 | .setBody("send condition message body") 48 | .build(); 49 | 50 | JSONObject multiLangKey = new JSONObject(); 51 | JSONObject titleKey = new JSONObject(); 52 | titleKey.put("en","好友请求"); 53 | JSONObject bodyKey = new JSONObject(); 54 | bodyKey.put("en","My name is %s, I am from %s."); 55 | multiLangKey.put("key1", titleKey); 56 | multiLangKey.put("key2", bodyKey); 57 | 58 | LightSettings lightSettings = LightSettings.builder().setColor(Color.builder().setAlpha(0f).setRed(0f).setBlue(1f).setGreen(1f).build()) 59 | .setLightOnDuration("3.5") 60 | .setLightOffDuration("5S") 61 | .build(); 62 | 63 | AndroidNotification androidNotification = AndroidNotification.builder().setIcon("/raw/ic_launcher2") 64 | .setColor("#AACCDD") 65 | .setSound("/raw/shake") 66 | .setDefaultSound(true) 67 | .setTag("tagBoom") 68 | .setClickAction(ClickAction.builder().setType(2).setUrl("https://www.huawei.com").build()) 69 | .setBodyLocKey("key2") 70 | .addBodyLocArgs("boy").addBodyLocArgs("dog") 71 | .setTitleLocKey("key1") 72 | .addTitleLocArgs("Girl").addTitleLocArgs("Cat") 73 | .setChannelId("Your Channel ID") 74 | .setNotifySummary("some summary") 75 | .setMultiLangkey(multiLangKey) 76 | .setStyle(1) 77 | .setBigTitle("send condition message title") 78 | .setBigBody("send condition message body") 79 | .setAutoClear(86400000) 80 | .setNotifyId(486) 81 | .setGroup("Group1") 82 | .setImportance(Importance.LOW.getValue()) 83 | .setLightSettings(lightSettings) 84 | .setBadge(BadgeNotification.builder().setAddNum(1).setBadgeClass("Classic").build()) 85 | .setVisibility(Visibility.PUBLIC.getValue()) 86 | .setForegroundShow(true) 87 | .build(); 88 | 89 | AndroidConfig androidConfig = AndroidConfig.builder().setCollapseKey(-1) 90 | .setUrgency(Urgency.HIGH.getValue()) 91 | .setTtl("10000s") 92 | .setBiTag("the_sample_bi_tag_for_receipt_service") 93 | .setNotification(androidNotification) 94 | .build(); 95 | 96 | String condition = "'targetTopic' in topics"; 97 | 98 | Message message = Message.builder().setNotification(notification) 99 | .setAndroidConfig(androidConfig) 100 | .setCondition(condition) 101 | .build(); 102 | 103 | SendResponse response = huaweiMessaging.sendMessage(message); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/examples/SendDataMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.examples; 17 | 18 | import com.huawei.push.exception.HuaweiMesssagingException; 19 | import com.huawei.push.message.AndroidConfig; 20 | import com.huawei.push.message.Message; 21 | import com.huawei.push.messaging.HuaweiApp; 22 | import com.huawei.push.messaging.HuaweiMessaging; 23 | import com.huawei.push.model.Urgency; 24 | import com.huawei.push.reponse.SendResponse; 25 | import com.huawei.push.util.InitAppUtils; 26 | 27 | public class SendDataMessage { 28 | /** 29 | * send data message 30 | * 31 | * @throws HuaweiMesssagingException 32 | */ 33 | public void sendTransparent() throws HuaweiMesssagingException { 34 | HuaweiApp app = InitAppUtils.initializeApp(); 35 | HuaweiMessaging huaweiMessaging = HuaweiMessaging.getInstance(app); 36 | 37 | AndroidConfig androidConfig = AndroidConfig.builder().setCollapseKey(-1) 38 | .setUrgency(Urgency.HIGH.getValue()) 39 | .setTtl("10000s") 40 | .setBiTag("the_sample_bi_tag_for_receipt_service") 41 | .build(); 42 | 43 | String token = "AND8rUp4etqJvbakK7qQoCVgFHnROXzH8o7B8fTl9rMP5VRFN83zU3Nvmabm3xw7e3gZjyBbp_wfO1jP-UyDQcZN_CtjBpoa7nx1WaVFe_3mqXMJ6nXJNUZcDyO_-k3sSw"; 44 | 45 | Message message = Message.builder() 46 | .setData("{'key1':'value1', 'key2':'value2'}") 47 | .setAndroidConfig(androidConfig) 48 | .addToken(token) 49 | .build(); 50 | 51 | SendResponse response = huaweiMessaging.sendMessage(message); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/examples/SendInstanceAppMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.examples; 17 | 18 | import com.alibaba.fastjson.JSONObject; 19 | import com.huawei.push.exception.HuaweiMesssagingException; 20 | import com.huawei.push.message.AndroidConfig; 21 | import com.huawei.push.message.Message; 22 | import com.huawei.push.messaging.HuaweiApp; 23 | import com.huawei.push.messaging.HuaweiMessaging; 24 | import com.huawei.push.reponse.SendResponse; 25 | import com.huawei.push.util.InitAppUtils; 26 | 27 | public class SendInstanceAppMessage { 28 | /** 29 | * send instance app message 30 | * 31 | * @throws HuaweiMesssagingException 32 | */ 33 | public void sendInstanceAppMessage() throws HuaweiMesssagingException { 34 | HuaweiApp app = InitAppUtils.initializeApp(); 35 | HuaweiMessaging huaweiMessaging = HuaweiMessaging.getInstance(app); 36 | 37 | String token = "AI838_-IxzMqKqeIoIqFgL9D5N8YunVqZXFU3jCohcmEkb1RMquoT7uxQkv3cXCv7IXwXjTsH0WK35DRrnLI6RBOWxqjnRqkbp6W5CFQj0zw09FG5sTuyZd2NHtxgVzUUg"; 38 | 39 | JSONObject params = new JSONObject(); 40 | params.put("key1", "test1"); 41 | params.put("key2", "test2"); 42 | 43 | JSONObject ringtone = new JSONObject(); 44 | ringtone.put("vibration", "true"); 45 | ringtone.put("breathLight", "true"); 46 | 47 | JSONObject msgBody = new JSONObject(); 48 | msgBody.put("title", "Welcome to use Huawei HMS Push Kit"); 49 | msgBody.put("description", "One of the best push platform on the planet!!!"); 50 | msgBody.put("page", ""); 51 | msgBody.put("params", params); 52 | msgBody.put("ringtone", ringtone); 53 | 54 | 55 | JSONObject msg = new JSONObject(); 56 | msg.put("pushtype", 0); 57 | msg.put("pushbody", msgBody); 58 | 59 | String data = msg.toJSONString(); 60 | 61 | AndroidConfig androidConfig = AndroidConfig.builder().setFastAppTargetType(1).build(); 62 | 63 | Message message = Message.builder().setData(data) 64 | .setAndroidConfig(androidConfig) 65 | .addToken(token) 66 | .build(); 67 | 68 | SendResponse response = huaweiMessaging.sendMessage(message); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/examples/SendNotifyMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.examples; 17 | 18 | import com.alibaba.fastjson.JSONObject; 19 | import com.huawei.push.android.AndroidNotification; 20 | import com.huawei.push.android.BadgeNotification; 21 | import com.huawei.push.android.Button; 22 | import com.huawei.push.android.ClickAction; 23 | import com.huawei.push.android.Color; 24 | import com.huawei.push.android.LightSettings; 25 | import com.huawei.push.exception.HuaweiMesssagingException; 26 | import com.huawei.push.message.AndroidConfig; 27 | import com.huawei.push.message.Message; 28 | import com.huawei.push.message.Notification; 29 | import com.huawei.push.messaging.HuaweiApp; 30 | import com.huawei.push.messaging.HuaweiMessaging; 31 | import com.huawei.push.model.Urgency; 32 | import com.huawei.push.model.Importance; 33 | import com.huawei.push.model.Visibility; 34 | import com.huawei.push.reponse.SendResponse; 35 | import com.huawei.push.util.InitAppUtils; 36 | 37 | public class SendNotifyMessage { 38 | /** 39 | * send notification message 40 | * 41 | * @throws HuaweiMesssagingException 42 | */ 43 | public void sendNotification() throws HuaweiMesssagingException { 44 | HuaweiApp app = InitAppUtils.initializeApp(); 45 | HuaweiMessaging huaweiMessaging = HuaweiMessaging.getInstance(app); 46 | 47 | Notification notification = Notification.builder().setTitle("sample title") 48 | .setBody("sample message body") 49 | .build(); 50 | 51 | JSONObject multiLangKey = new JSONObject(); 52 | JSONObject titleKey = new JSONObject(); 53 | titleKey.put("en","好友请求"); 54 | JSONObject bodyKey = new JSONObject(); 55 | bodyKey.put("en","My name is %s, I am from %s."); 56 | multiLangKey.put("key1", titleKey); 57 | multiLangKey.put("key2", bodyKey); 58 | 59 | LightSettings lightSettings = LightSettings.builder().setColor(Color.builder().setAlpha(0f).setRed(0f).setBlue(1f).setGreen(1f).build()) 60 | .setLightOnDuration("3.5") 61 | .setLightOffDuration("5S") 62 | .build(); 63 | 64 | AndroidNotification androidNotification = AndroidNotification.builder().setIcon("/raw/ic_launcher2") 65 | .setColor("#AACCDD") 66 | .setSound("/raw/shake") 67 | .setDefaultSound(true) 68 | .setTag("tagBoom") 69 | .setClickAction(ClickAction.builder().setType(2).setUrl("https://www.huawei.com").build()) 70 | .setBodyLocKey("key2") 71 | .addBodyLocArgs("boy").addBodyLocArgs("dog") 72 | .setTitleLocKey("key1") 73 | .addTitleLocArgs("Girl").addTitleLocArgs("Cat") 74 | .setChannelId("Your Channel ID") 75 | .setNotifySummary("some summary") 76 | .setMultiLangkey(multiLangKey) 77 | .setStyle(1) 78 | .setBigTitle("Big Boom Title") 79 | .setBigBody("Big Boom Body") 80 | .setAutoClear(86400000) 81 | .setNotifyId(486) 82 | .setGroup("Group1") 83 | .setImportance(Importance.LOW.getValue()) 84 | .setLightSettings(lightSettings) 85 | .setBadge(BadgeNotification.builder().setAddNum(1).setBadgeClass("Classic").build()) 86 | .setVisibility(Visibility.PUBLIC.getValue()) 87 | .setForegroundShow(true) 88 | .addInboxContent("content1").addInboxContent("content2").addInboxContent("content3").addInboxContent("content4").addInboxContent("content5") 89 | .addButton(Button.builder().setName("button1").setActionType(0).build()) 90 | .addButton(Button.builder().setName("button2").setActionType(1).setIntentType(0).setIntent("https://com.huawei.hms.hmsdemo/deeplink").build()) 91 | .addButton(Button.builder().setName("button3").setActionType(4).setData("your share link").build()) 92 | .build(); 93 | 94 | AndroidConfig androidConfig = AndroidConfig.builder().setCollapseKey(-1) 95 | .setUrgency(Urgency.HIGH.getValue()) 96 | .setTtl("10000s") 97 | .setBiTag("the_sample_bi_tag_for_receipt_service") 98 | .setNotification(androidNotification) 99 | .build(); 100 | 101 | Message message = Message.builder().setNotification(notification) 102 | .setAndroidConfig(androidConfig) 103 | .addToken("AND8rUp4etqJvbakK7qQoCVgFHnROXzH8o7B8fTl9rMP5VRFN83zU3Nvmabm3xw7e3gZjyBbp_wfO1jP-UyDQcZN_CtjBpoa7nx1WaVFe_3mqXMJ6nXJNUZcDyO_-k3sSw") 104 | .build(); 105 | 106 | SendResponse response = huaweiMessaging.sendMessage(message); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/examples/SendTestMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.examples; 17 | 18 | import com.alibaba.fastjson.JSONObject; 19 | import com.huawei.push.android.AndroidNotification; 20 | import com.huawei.push.android.BadgeNotification; 21 | import com.huawei.push.android.ClickAction; 22 | import com.huawei.push.android.Color; 23 | import com.huawei.push.android.LightSettings; 24 | import com.huawei.push.exception.HuaweiMesssagingException; 25 | import com.huawei.push.message.AndroidConfig; 26 | import com.huawei.push.message.Message; 27 | import com.huawei.push.message.Notification; 28 | import com.huawei.push.messaging.HuaweiApp; 29 | import com.huawei.push.messaging.HuaweiMessaging; 30 | import com.huawei.push.model.Urgency; 31 | import com.huawei.push.model.Importance; 32 | import com.huawei.push.model.Visibility; 33 | import com.huawei.push.reponse.SendResponse; 34 | import com.huawei.push.util.InitAppUtils; 35 | 36 | public class SendTestMessage { 37 | public void sendTestMessage() throws HuaweiMesssagingException { 38 | HuaweiApp app = InitAppUtils.initializeApp(); 39 | HuaweiMessaging huaweiMessaging = HuaweiMessaging.getInstance(app); 40 | 41 | Notification notification = Notification.builder().setTitle("sample title") 42 | .setBody("sample message body") 43 | .build(); 44 | 45 | JSONObject multiLangKey = new JSONObject(); 46 | JSONObject titleKey = new JSONObject(); 47 | titleKey.put("en","好友请求"); 48 | JSONObject bodyKey = new JSONObject(); 49 | bodyKey.put("en","My name is %s, I am from %s."); 50 | multiLangKey.put("key1", titleKey); 51 | multiLangKey.put("key2", bodyKey); 52 | 53 | LightSettings lightSettings = LightSettings.builder().setColor(Color.builder().setAlpha(0f).setRed(0f).setBlue(1f).setGreen(1f).build()) 54 | .setLightOnDuration("3.5") 55 | .setLightOffDuration("5S") 56 | .build(); 57 | 58 | AndroidNotification androidNotification = AndroidNotification.builder().setIcon("/raw/ic_launcher2") 59 | .setColor("#AACCDD") 60 | .setSound("/raw/shake") 61 | .setDefaultSound(true) 62 | .setTag("tagBoom") 63 | .setClickAction(ClickAction.builder().setType(2).setUrl("https://www.huawei.com").build()) 64 | .setBodyLocKey("key2") 65 | .addBodyLocArgs("boy").addBodyLocArgs("dog") 66 | .setTitleLocKey("key1") 67 | .addTitleLocArgs("Girl").addTitleLocArgs("Cat") 68 | .setChannelId("Your Channel ID") 69 | .setNotifySummary("some summary") 70 | .setMultiLangkey(multiLangKey) 71 | .setStyle(1) 72 | .setBigTitle("Big Boom Title") 73 | .setBigBody("Big Boom Body") 74 | .setAutoClear(86400000) 75 | .setNotifyId(486) 76 | .setGroup("Group1") 77 | .setImportance(Importance.LOW.getValue()) 78 | .setLightSettings(lightSettings) 79 | .setBadge(BadgeNotification.builder().setAddNum(1).setBadgeClass("Classic").build()) 80 | .setVisibility(Visibility.PUBLIC.getValue()) 81 | .setForegroundShow(true) 82 | .build(); 83 | 84 | AndroidConfig androidConfig = AndroidConfig.builder().setCollapseKey(-1) 85 | .setUrgency(Urgency.HIGH.getValue()) 86 | .setTtl("10000s") 87 | .setBiTag("the_sample_bi_tag_for_receipt_service") 88 | .setNotification(androidNotification) 89 | .build(); 90 | 91 | Message message = Message.builder().setNotification(notification) 92 | .setAndroidConfig(androidConfig) 93 | .addToken("AND8rUp4etqJvbakK7qQoCVgFHnROXzH8o7B8fTl9rMP5VRFN83zU3Nvmabm3xw7e3gZjyBbp_wfO1jP-UyDQcZN_CtjBpoa7nx1WaVFe_3mqXMJ6nXJNUZcDyO_-k3sSw") 94 | .build(); 95 | 96 | SendResponse response = huaweiMessaging.sendMessage(message, true); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/examples/SendTopicMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.examples; 17 | 18 | import com.alibaba.fastjson.JSONObject; 19 | import com.huawei.push.android.AndroidNotification; 20 | import com.huawei.push.android.BadgeNotification; 21 | import com.huawei.push.android.ClickAction; 22 | import com.huawei.push.android.Color; 23 | import com.huawei.push.android.LightSettings; 24 | import com.huawei.push.exception.HuaweiMesssagingException; 25 | import com.huawei.push.message.AndroidConfig; 26 | import com.huawei.push.message.Message; 27 | import com.huawei.push.message.Notification; 28 | import com.huawei.push.messaging.HuaweiApp; 29 | import com.huawei.push.messaging.HuaweiMessaging; 30 | import com.huawei.push.model.Urgency; 31 | import com.huawei.push.model.Importance; 32 | import com.huawei.push.model.Visibility; 33 | import com.huawei.push.reponse.SendResponse; 34 | import com.huawei.push.util.InitAppUtils; 35 | 36 | public class SendTopicMessage { 37 | /** 38 | * send message to topic 39 | * 40 | * @throws HuaweiMesssagingException 41 | */ 42 | public void sendToTopic() throws HuaweiMesssagingException { 43 | HuaweiApp app = InitAppUtils.initializeApp(); 44 | HuaweiMessaging huaweiMessaging = HuaweiMessaging.getInstance(app); 45 | 46 | Notification notification = Notification.builder().setTitle("send topic message title") 47 | .setBody("send topic message title") 48 | .build(); 49 | 50 | JSONObject multiLangKey = new JSONObject(); 51 | JSONObject titleKey = new JSONObject(); 52 | titleKey.put("en","好友请求"); 53 | JSONObject bodyKey = new JSONObject(); 54 | bodyKey.put("en","My name is %s, I am from %s."); 55 | multiLangKey.put("key1", titleKey); 56 | multiLangKey.put("key2", bodyKey); 57 | 58 | LightSettings lightSettings = LightSettings.builder().setColor(Color.builder().setAlpha(0f).setRed(0f).setBlue(1f).setGreen(1f).build()) 59 | .setLightOnDuration("3.5") 60 | .setLightOffDuration("5S") 61 | .build(); 62 | 63 | AndroidNotification androidNotification = AndroidNotification.builder().setIcon("/raw/ic_launcher2") 64 | .setColor("#AACCDD") 65 | .setSound("/raw/shake") 66 | .setDefaultSound(true) 67 | .setTag("tagBoom") 68 | .setClickAction(ClickAction.builder().setType(2).setUrl("https://www.huawei.com").build()) 69 | .setBodyLocKey("key2") 70 | .addBodyLocArgs("boy").addBodyLocArgs("dog") 71 | .setTitleLocKey("key1") 72 | .addTitleLocArgs("Girl").addTitleLocArgs("Cat") 73 | .setChannelId("Your Channel ID") 74 | .setNotifySummary("some summary") 75 | .setMultiLangkey(multiLangKey) 76 | .setStyle(1) 77 | .setBigTitle("send topic message title") 78 | .setBigBody("send topic message body") 79 | .setAutoClear(86400000) 80 | .setNotifyId(486) 81 | .setGroup("Group1") 82 | .setImportance(Importance.LOW.getValue()) 83 | .setLightSettings(lightSettings) 84 | .setBadge(BadgeNotification.builder().setAddNum(1).setBadgeClass("Classic").build()) 85 | .setVisibility(Visibility.PUBLIC.getValue()) 86 | .setForegroundShow(true) 87 | .build(); 88 | 89 | AndroidConfig androidConfig = AndroidConfig.builder().setCollapseKey(-1) 90 | .setUrgency(Urgency.HIGH.getValue()) 91 | .setTtl("10000s") 92 | .setBiTag("the_sample_bi_tag_for_receipt_service") 93 | .setNotification(androidNotification) 94 | .build(); 95 | 96 | Message message = Message.builder().setNotification(notification) 97 | .setAndroidConfig(androidConfig) 98 | .setTopic("targetTopic") 99 | .build(); 100 | 101 | SendResponse response = huaweiMessaging.sendMessage(message); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/examples/SendWebpushMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.examples; 17 | 18 | import com.huawei.push.exception.HuaweiMesssagingException; 19 | import com.huawei.push.message.Message; 20 | import com.huawei.push.message.Notification; 21 | import com.huawei.push.message.WebPushConfig; 22 | import com.huawei.push.messaging.HuaweiApp; 23 | import com.huawei.push.messaging.HuaweiMessaging; 24 | import com.huawei.push.reponse.SendResponse; 25 | import com.huawei.push.util.InitAppUtils; 26 | import com.huawei.push.webpush.WebActions; 27 | import com.huawei.push.webpush.WebHmsOptions; 28 | import com.huawei.push.webpush.WebNotification; 29 | import com.huawei.push.webpush.WebpushHeaders; 30 | 31 | public class SendWebpushMessage { 32 | 33 | public void sendWebpushMessage() throws HuaweiMesssagingException { 34 | HuaweiApp app = InitAppUtils.initializeApp(); 35 | HuaweiMessaging huaweiMessaging = HuaweiMessaging.getInstance(app); 36 | 37 | Notification notification = Notification.builder().setTitle("Big News") 38 | .setBody("This is a Big apple news1202") 39 | .build(); 40 | 41 | WebpushHeaders webpushHeaders = WebpushHeaders.builder() 42 | .setTtl("990") 43 | .setUrgency("low") 44 | .setTopic("12313") 45 | .build(); 46 | 47 | WebNotification webNotification = WebNotification.builder().setTitle("Web Push Title") 48 | .setBody("Web Push body") 49 | .setIcon("https://developer-portalres-drcn.dbankcdn.com/system/modules/org.opencms.portal.template.core/\resources/images/icon_Promotion.png") 50 | .addAction(WebActions.builder().setAction("click").setIcon("").setTitle("title").build()) 51 | .setBadge("badge") 52 | .setDir("auto") 53 | .setImage("image url") 54 | .setLang("en") 55 | .setRenotify(false) 56 | .setRequireInteraction(false) 57 | .setSilent(true) 58 | .setTag("tag") 59 | .setTimestamp(32323L) 60 | .addVibrate(1).addVibrate(2).addVibrate(3) 61 | .build(); 62 | 63 | WebHmsOptions webHmsOptions = WebHmsOptions.builder().setLink("http://www.xx.com").build(); 64 | 65 | WebPushConfig webpush = WebPushConfig.builder().setHeaders(webpushHeaders) 66 | .setNotification(webNotification) 67 | .setWebHmsOptions(webHmsOptions) 68 | .build(); 69 | 70 | String token = "cTW+APk7SomjRb2dOB7UIfyn_6q-hdNR8TfbkEcRus7fR2DrfXqS6EwINiuy1dhceiPXgE9t6rYkVNuRrcFcCPsCfNAIVR4N54Whfhow4r51hY05MB43r7461pls0qj9nhF4gQ"; 71 | 72 | Message message = Message.builder().setNotification(notification) 73 | .setData("nb!") 74 | .setWebpush(webpush) 75 | .addToken(token) 76 | .build(); 77 | 78 | SendResponse response = huaweiMessaging.sendMessage(message); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/exception/HuaweiException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.exception; 17 | 18 | import com.google.common.base.Strings; 19 | import com.huawei.push.util.ValidatorUtils; 20 | 21 | /** 22 | * exceptions 23 | */ 24 | public class HuaweiException extends Exception { 25 | 26 | public HuaweiException(String detailMessage) { 27 | super(detailMessage); 28 | ValidatorUtils.checkArgument(!Strings.isNullOrEmpty(detailMessage), "Detail message must not be empty"); 29 | } 30 | 31 | public HuaweiException(String detailMessage, Throwable cause) { 32 | super(detailMessage, cause); 33 | ValidatorUtils.checkArgument(!Strings.isNullOrEmpty(detailMessage), "Detail message must not be empty"); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/exception/HuaweiMesssagingException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.exception; 17 | 18 | import com.google.common.base.Strings; 19 | import com.huawei.push.util.ValidatorUtils; 20 | 21 | public class HuaweiMesssagingException extends HuaweiException { 22 | private final String errorCode; 23 | 24 | public HuaweiMesssagingException(String errorCode, String message) { 25 | super(message); 26 | ValidatorUtils.checkArgument(!Strings.isNullOrEmpty(errorCode)); 27 | this.errorCode = errorCode; 28 | } 29 | 30 | public HuaweiMesssagingException(String errorCode, String message, Throwable cause) { 31 | super(message, cause); 32 | ValidatorUtils.checkArgument(!Strings.isNullOrEmpty(errorCode)); 33 | this.errorCode = errorCode; 34 | } 35 | 36 | public String getErrorCode() { 37 | return errorCode; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/message/AndroidConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.message; 17 | 18 | import com.alibaba.fastjson.annotation.JSONField; 19 | import com.huawei.push.android.AndroidNotification; 20 | import com.huawei.push.model.Urgency; 21 | import com.huawei.push.util.ValidatorUtils; 22 | 23 | import org.apache.commons.lang3.StringUtils; 24 | 25 | public class AndroidConfig { 26 | private static final String TTL_PATTERN = "\\d+|\\d+[sS]|\\d+.\\d{1,9}|\\d+.\\d{1,9}[sS]"; 27 | 28 | @JSONField(name = "collapse_key") 29 | private Integer collapseKey; 30 | 31 | @JSONField(name = "urgency") 32 | private String urgency; 33 | 34 | @JSONField(name = "category") 35 | private String category; 36 | 37 | @JSONField(name = "ttl") 38 | private String ttl; 39 | 40 | @JSONField(name = "bi_tag") 41 | private String biTag; 42 | 43 | @JSONField(name = "fast_app_target") 44 | private Integer fastAppTargetType; 45 | 46 | @JSONField(name = "data") 47 | private String data; 48 | 49 | @JSONField(name = "notification") 50 | private AndroidNotification notification; 51 | 52 | @JSONField(name = "receipt_id") 53 | private String receiptId; 54 | 55 | public AndroidConfig(Builder builder) { 56 | this.collapseKey = builder.collapseKey; 57 | this.urgency = builder.urgency; 58 | this.category = builder.category; 59 | 60 | if (null != builder.ttl) { 61 | this.ttl = builder.ttl; 62 | } else { 63 | this.ttl = null; 64 | } 65 | 66 | this.biTag = builder.biTag; 67 | this.fastAppTargetType = builder.fastAppTargetType; 68 | this.data = builder.data; 69 | this.notification = builder.notification; 70 | this.receiptId = builder.receiptId; 71 | } 72 | 73 | /** 74 | * check androidConfig's parameters 75 | * 76 | * @param notification whcic is in message 77 | */ 78 | public void check(Notification notification) { 79 | if (this.collapseKey != null) { 80 | ValidatorUtils.checkArgument((this.collapseKey >= -1 && this.collapseKey <= 100), "Collapse Key should be [-1, 100]"); 81 | } 82 | 83 | if (this.urgency != null) { 84 | ValidatorUtils.checkArgument(StringUtils.equals(this.urgency, Urgency.HIGH.getValue()) 85 | || StringUtils.equals(this.urgency, Urgency.NORMAL.getValue()), 86 | "urgency shouid be [HIGH, NORMAL]"); 87 | } 88 | 89 | if (StringUtils.isNotEmpty(this.ttl)) { 90 | ValidatorUtils.checkArgument(this.ttl.matches(AndroidConfig.TTL_PATTERN), "The TTL's format is wrong"); 91 | } 92 | 93 | if (this.fastAppTargetType != null) { 94 | ValidatorUtils.checkArgument(this.fastAppTargetType == 1 || this.fastAppTargetType == 2, "Invalid fast app target type[one of 1 or 2]"); 95 | } 96 | 97 | if (null != this.notification) { 98 | this.notification.check(notification); 99 | } 100 | } 101 | 102 | /** 103 | * getter 104 | */ 105 | public Integer getCollapseKey() { 106 | return collapseKey; 107 | } 108 | 109 | public String getTtl() { 110 | return ttl; 111 | } 112 | 113 | public String getCategory() { 114 | return category; 115 | } 116 | 117 | public String getBiTag() { 118 | return biTag; 119 | } 120 | 121 | public Integer getFastAppTargetType() { 122 | return fastAppTargetType; 123 | } 124 | 125 | public AndroidNotification getNotification() { 126 | return notification; 127 | } 128 | 129 | public String getUrgency() { 130 | return urgency; 131 | } 132 | 133 | public String getData() { 134 | return data; 135 | } 136 | 137 | public String getReceiptId() { return receiptId; } 138 | 139 | /** 140 | * builder 141 | */ 142 | public static Builder builder() { 143 | return new Builder(); 144 | } 145 | 146 | public static class Builder { 147 | private Integer collapseKey; 148 | private String urgency; 149 | private String category; 150 | private String ttl; 151 | private String biTag; 152 | private Integer fastAppTargetType; 153 | private String data; 154 | 155 | private AndroidNotification notification; 156 | private String receiptId; 157 | 158 | private Builder() { 159 | } 160 | 161 | public Builder setCollapseKey(Integer collapseKey) { 162 | this.collapseKey = collapseKey; 163 | return this; 164 | } 165 | 166 | public Builder setUrgency(String urgency) { 167 | this.urgency = urgency; 168 | return this; 169 | } 170 | 171 | public Builder setCategory(String category) { 172 | this.category = category; 173 | return this; 174 | } 175 | 176 | /** 177 | * time-to-live 178 | */ 179 | public Builder setTtl(String ttl) { 180 | this.ttl = ttl; 181 | return this; 182 | } 183 | 184 | public Builder setBiTag(String biTag) { 185 | this.biTag = biTag; 186 | return this; 187 | } 188 | 189 | public Builder setFastAppTargetType(Integer fastAppTargetType) { 190 | this.fastAppTargetType = fastAppTargetType; 191 | return this; 192 | } 193 | 194 | public Builder setData(String data) { 195 | this.data = data; 196 | return this; 197 | } 198 | 199 | public Builder setNotification(AndroidNotification notification) { 200 | this.notification = notification; 201 | return this; 202 | } 203 | 204 | public AndroidConfig build() { 205 | return new AndroidConfig(this); 206 | } 207 | 208 | public Builder setReceiptId(String receiptId) { 209 | this.receiptId = receiptId; 210 | return this; 211 | } 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/message/ApnsConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.message; 17 | 18 | import com.alibaba.fastjson.annotation.JSONField; 19 | import com.huawei.push.apns.ApnsHeaders; 20 | import com.huawei.push.apns.ApnsHmsOptions; 21 | import com.huawei.push.apns.Aps; 22 | import com.huawei.push.util.CollectionUtils; 23 | 24 | import java.util.HashMap; 25 | import java.util.Map; 26 | 27 | public class ApnsConfig { 28 | @JSONField(name = "hms_options") 29 | private ApnsHmsOptions hmsOptions; 30 | 31 | @JSONField(name = "headers") 32 | private ApnsHeaders apnsHeaders; 33 | 34 | @JSONField(name = "payload") 35 | private Map payload = new HashMap<>(); 36 | 37 | public void check() { 38 | if (this.hmsOptions != null) { 39 | this.hmsOptions.check(); 40 | } 41 | if (this.apnsHeaders != null) { 42 | this.apnsHeaders.check(); 43 | } 44 | if (this.payload != null) { 45 | if (this.payload.get("aps") != null) { 46 | Aps aps = (Aps) this.payload.get("aps"); 47 | aps.check(); 48 | } 49 | } 50 | } 51 | 52 | public ApnsConfig(Builder builder) { 53 | this.hmsOptions = builder.hmsOptions; 54 | this.apnsHeaders = builder.apnsHeaders; 55 | if (!CollectionUtils.isEmpty(builder.payload) || builder.aps != null) { 56 | if (!CollectionUtils.isEmpty(builder.payload)) { 57 | this.payload.putAll(builder.payload); 58 | } 59 | if (builder.aps != null) { 60 | this.payload.put("aps", builder.aps); 61 | } 62 | } else { 63 | this.payload = null; 64 | } 65 | } 66 | 67 | public ApnsHmsOptions getHmsOptions() { 68 | return hmsOptions; 69 | } 70 | 71 | public Map getPayload() { 72 | return payload; 73 | } 74 | 75 | public ApnsHeaders getApnsHeaders() { 76 | return apnsHeaders; 77 | } 78 | 79 | /** 80 | * builder 81 | */ 82 | public static Builder builder() { 83 | return new Builder(); 84 | } 85 | 86 | public static class Builder { 87 | private ApnsHmsOptions hmsOptions; 88 | private Map payload = new HashMap<>(); 89 | private ApnsHeaders apnsHeaders; 90 | private Aps aps; 91 | 92 | public Builder setHmsOptions(ApnsHmsOptions hmsOptions) { 93 | this.hmsOptions = hmsOptions; 94 | return this; 95 | } 96 | 97 | public Builder addPayload(String key, Object value) { 98 | this.payload.put(key, value); 99 | return this; 100 | } 101 | 102 | public Builder addAllPayload(Map map) { 103 | this.payload.putAll(map); 104 | return this; 105 | } 106 | 107 | public Builder setApnsHeaders(ApnsHeaders apnsHeaders) { 108 | this.apnsHeaders = apnsHeaders; 109 | return this; 110 | } 111 | 112 | public Builder addPayloadAps(Aps aps) { 113 | this.aps = aps; 114 | return this; 115 | } 116 | 117 | public Builder addPayload(Aps aps) { 118 | this.aps = aps; 119 | return this; 120 | } 121 | 122 | public ApnsConfig build() { 123 | return new ApnsConfig(this); 124 | } 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/message/Message.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.message; 17 | 18 | import com.alibaba.fastjson.annotation.JSONField; 19 | import com.google.common.base.Strings; 20 | import com.google.common.primitives.Booleans; 21 | import com.huawei.push.util.CollectionUtils; 22 | import com.huawei.push.util.ValidatorUtils; 23 | 24 | import org.apache.commons.lang3.StringUtils; 25 | 26 | import java.util.ArrayList; 27 | import java.util.List; 28 | 29 | public class Message { 30 | @JSONField(name = "data") 31 | private String data; 32 | 33 | @JSONField(name = "notification") 34 | private Notification notification; 35 | 36 | @JSONField(name = "android") 37 | private AndroidConfig androidConfig; 38 | 39 | @JSONField(name = "apns") 40 | private ApnsConfig apns; 41 | 42 | @JSONField(name = "webpush") 43 | private WebPushConfig webpush; 44 | 45 | @JSONField(name = "token") 46 | private List token = new ArrayList<>(); 47 | 48 | @JSONField(name = "topic") 49 | private String topic; 50 | 51 | @JSONField(name = "condition") 52 | private String condition; 53 | 54 | private Message(Builder builder) { 55 | this.data = builder.data; 56 | this.notification = builder.notification; 57 | this.androidConfig = builder.androidConfig; 58 | this.apns = builder.apns; 59 | this.webpush = builder.webpush; 60 | 61 | if (!CollectionUtils.isEmpty(builder.token)) { 62 | this.token.addAll(builder.token); 63 | } else { 64 | this.token = null; 65 | } 66 | 67 | this.topic = builder.topic; 68 | this.condition = builder.condition; 69 | 70 | /** check after message is created */ 71 | check(); 72 | } 73 | 74 | /** 75 | * check message's parameters 76 | */ 77 | public void check() { 78 | 79 | int count = Booleans.countTrue( 80 | !CollectionUtils.isEmpty(this.token), 81 | !Strings.isNullOrEmpty(this.topic), 82 | !Strings.isNullOrEmpty(this.condition) 83 | ); 84 | 85 | ValidatorUtils.checkArgument(count == 1, "Exactly one of token, topic or condition must be specified"); 86 | 87 | if (this.notification != null) { 88 | this.notification.check(); 89 | } 90 | 91 | if (null != this.androidConfig) { 92 | this.androidConfig.check(this.notification); 93 | } 94 | 95 | if (this.apns != null) { 96 | this.apns.check(); 97 | } 98 | 99 | if (this.webpush != null) { 100 | this.webpush.check(); 101 | } 102 | } 103 | 104 | /** 105 | * getter 106 | */ 107 | public String getData() { 108 | return data; 109 | } 110 | 111 | public Notification getNotification() { 112 | return notification; 113 | } 114 | 115 | public AndroidConfig getAndroidConfig() { 116 | return androidConfig; 117 | } 118 | 119 | public ApnsConfig getApns() { 120 | return apns; 121 | } 122 | 123 | public WebPushConfig getWebpush() { 124 | return webpush; 125 | } 126 | 127 | public List getToken() { 128 | return token; 129 | } 130 | 131 | public String getTopic() { 132 | return topic; 133 | } 134 | 135 | public String getCondition() { 136 | return condition; 137 | } 138 | 139 | /** 140 | * builder 141 | * 142 | * @return 143 | */ 144 | public static Builder builder() { 145 | return new Builder(); 146 | } 147 | 148 | /** 149 | * push message builder 150 | */ 151 | public static class Builder { 152 | private String data; 153 | private Notification notification; 154 | private AndroidConfig androidConfig; 155 | private ApnsConfig apns; 156 | private WebPushConfig webpush; 157 | private List token = new ArrayList<>(); 158 | private String topic; 159 | private String condition; 160 | 161 | private Builder() { 162 | } 163 | 164 | public Builder setData(String data) { 165 | this.data = data; 166 | return this; 167 | } 168 | 169 | public Builder setNotification(Notification notification) { 170 | this.notification = notification; 171 | return this; 172 | } 173 | 174 | public Builder setAndroidConfig(AndroidConfig androidConfig) { 175 | this.androidConfig = androidConfig; 176 | return this; 177 | } 178 | 179 | public Builder setApns(ApnsConfig apns) { 180 | this.apns = apns; 181 | return this; 182 | } 183 | 184 | public Builder setWebpush(WebPushConfig webpush) { 185 | this.webpush = webpush; 186 | return this; 187 | } 188 | 189 | public Builder addToken(String token) { 190 | this.token.add(token); 191 | return this; 192 | } 193 | 194 | public Builder addAllToken(List tokens) { 195 | this.token.addAll(tokens); 196 | return this; 197 | } 198 | 199 | public Builder setTopic(String topic) { 200 | this.topic = topic; 201 | return this; 202 | } 203 | 204 | public Builder setCondition(String condition) { 205 | this.condition = condition; 206 | return this; 207 | } 208 | 209 | public Message build() { 210 | return new Message(this); 211 | } 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/message/Notification.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.message; 17 | 18 | import com.alibaba.fastjson.annotation.JSONField; 19 | import com.huawei.push.util.ValidatorUtils; 20 | 21 | import java.util.Locale; 22 | 23 | public class Notification { 24 | @JSONField(name = "title") 25 | private String title; 26 | 27 | @JSONField(name = "body") 28 | private String body; 29 | 30 | @JSONField(name = "image") 31 | private String image; 32 | 33 | public Notification() { 34 | } 35 | 36 | public Notification(String title, String body) { 37 | this.title = title; 38 | this.body = body; 39 | } 40 | 41 | public Notification(String title, String body, String image) { 42 | this.title = title; 43 | this.body = body; 44 | this.image = image; 45 | } 46 | 47 | public Notification(Builder builder) { 48 | this.title = builder.title; 49 | this.body = builder.body; 50 | this.image = builder.image; 51 | } 52 | 53 | public void check() { 54 | if (this.image != null) { 55 | ValidatorUtils.checkArgument(this.image.toLowerCase(Locale.getDefault()).trim().startsWith("https"), "image's url should start with HTTPS"); 56 | } 57 | } 58 | 59 | public String getTitle() { 60 | return title; 61 | } 62 | 63 | public void setTitle(String title) { 64 | this.title = title; 65 | } 66 | 67 | public String getBody() { 68 | return body; 69 | } 70 | 71 | public void setBody(String body) { 72 | this.body = body; 73 | } 74 | 75 | public String getImage() { 76 | return image; 77 | } 78 | 79 | public void setImage(String image) { 80 | this.image = image; 81 | } 82 | 83 | /** 84 | * builder 85 | * 86 | * @return 87 | */ 88 | public static Builder builder() { 89 | return new Builder(); 90 | } 91 | 92 | /** 93 | * push message builder 94 | */ 95 | public static class Builder { 96 | private String title; 97 | 98 | private String body; 99 | 100 | private String image; 101 | 102 | public Builder setTitle(String title) { 103 | this.title = title; 104 | return this; 105 | } 106 | 107 | public Builder setBody(String body) { 108 | this.body = body; 109 | return this; 110 | } 111 | 112 | public Builder setImage(String image) { 113 | this.image = image; 114 | return this; 115 | } 116 | 117 | public Notification build() { 118 | return new Notification(this); 119 | } 120 | 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/message/TokenMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.message; 17 | 18 | import com.alibaba.fastjson.annotation.JSONField; 19 | 20 | public class TokenMessage { 21 | @JSONField(name = "token") 22 | private String token; 23 | 24 | public String getToken() { 25 | return token; 26 | } 27 | 28 | public TokenMessage(Builder builder){ 29 | this.token = builder.token; 30 | } 31 | 32 | /** 33 | * builder 34 | * 35 | * @return 36 | */ 37 | public static Builder builder() { 38 | return new Builder(); 39 | } 40 | 41 | public static class Builder { 42 | private String token; 43 | 44 | public Builder setToken(String token) { 45 | this.token = token; 46 | return this; 47 | } 48 | 49 | public TokenMessage build(){ 50 | return new TokenMessage(this); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/message/TopicMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.message; 17 | 18 | import com.alibaba.fastjson.annotation.JSONField; 19 | import com.huawei.push.util.CollectionUtils; 20 | 21 | import java.util.ArrayList; 22 | import java.util.List; 23 | 24 | public class TopicMessage { 25 | @JSONField(name = "topic") 26 | private String topic; 27 | 28 | @JSONField(name = "tokenArray") 29 | private List tokenArray = new ArrayList(); 30 | 31 | @JSONField(name = "token") 32 | private String token; 33 | 34 | public String getTopic() { 35 | return topic; 36 | } 37 | 38 | public List getTokenArray() { 39 | return tokenArray; 40 | } 41 | 42 | public String getToken() { 43 | return token; 44 | } 45 | 46 | private TopicMessage(Builder builder) { 47 | this.topic = builder.topic; 48 | if (!CollectionUtils.isEmpty(builder.tokenArray)) { 49 | this.tokenArray.addAll(builder.tokenArray); 50 | } else { 51 | this.tokenArray = null; 52 | } 53 | this.token = builder.token; 54 | } 55 | 56 | /** 57 | * builder 58 | * 59 | * @return 60 | */ 61 | public static Builder builder() { 62 | return new Builder(); 63 | } 64 | 65 | public static class Builder { 66 | private String topic; 67 | private List tokenArray = new ArrayList(); 68 | private String token; 69 | 70 | public Builder setTopic(String topic) { 71 | this.topic = topic; 72 | return this; 73 | } 74 | 75 | public Builder addToken(String token) { 76 | this.tokenArray.add(token); 77 | return this; 78 | } 79 | 80 | public Builder addAllToken(List tokenArray) { 81 | this.tokenArray.addAll(tokenArray); 82 | return this; 83 | } 84 | 85 | public Builder setToken(String token) { 86 | this.token = token; 87 | return this; 88 | } 89 | 90 | public TopicMessage build() { 91 | return new TopicMessage(this); 92 | } 93 | 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/message/WebPushConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.message; 17 | 18 | import com.alibaba.fastjson.annotation.JSONField; 19 | import com.huawei.push.webpush.WebHmsOptions; 20 | import com.huawei.push.webpush.WebNotification; 21 | import com.huawei.push.webpush.WebpushHeaders; 22 | 23 | public class WebPushConfig { 24 | @JSONField(name = "headers") 25 | private WebpushHeaders headers; 26 | 27 | @JSONField(name = "data") 28 | private String data; 29 | 30 | @JSONField(name = "notification") 31 | private WebNotification notification; 32 | 33 | @JSONField(name = "hms_options") 34 | private WebHmsOptions webHmsOptions; 35 | 36 | public WebpushHeaders getHeaders() { 37 | return headers; 38 | } 39 | 40 | public String getData() { 41 | return data; 42 | } 43 | 44 | public WebNotification getNotification() { 45 | return notification; 46 | } 47 | 48 | public WebHmsOptions getWebHmsOptions() { 49 | return webHmsOptions; 50 | } 51 | 52 | public WebPushConfig(Builder builder) { 53 | this.headers = builder.headers; 54 | this.data = builder.data; 55 | this.notification = builder.notification; 56 | this.webHmsOptions = builder.webHmsOptions; 57 | } 58 | 59 | public void check() { 60 | if (this.headers != null) { 61 | this.headers.check(); 62 | } 63 | if (this.notification != null) { 64 | this.notification.check(); 65 | } 66 | if (this.webHmsOptions != null) { 67 | this.webHmsOptions.check(); 68 | } 69 | } 70 | 71 | /** 72 | * builder 73 | */ 74 | public static Builder builder() { 75 | return new Builder(); 76 | } 77 | 78 | public static class Builder { 79 | private WebpushHeaders headers; 80 | 81 | private String data; 82 | 83 | private WebNotification notification; 84 | 85 | private WebHmsOptions webHmsOptions; 86 | 87 | public Builder setHeaders(WebpushHeaders headers) { 88 | this.headers = headers; 89 | return this; 90 | } 91 | 92 | public Builder setData(String data) { 93 | this.data = data; 94 | return this; 95 | } 96 | 97 | public Builder setNotification(WebNotification notification) { 98 | this.notification = notification; 99 | return this; 100 | } 101 | 102 | public Builder setWebHmsOptions(WebHmsOptions webHmsOptions) { 103 | this.webHmsOptions = webHmsOptions; 104 | return this; 105 | } 106 | 107 | public WebPushConfig build() { 108 | return new WebPushConfig(this); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/messaging/HuaweiApp.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2017 Google Inc. 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | 15 | * 2019.12.15-Changed constructor HuaweiApp 16 | * 2019.12.15-Changed method initializeApp 17 | * Huawei Technologies Co., Ltd. 18 | * 19 | */ 20 | package com.huawei.push.messaging; 21 | 22 | import com.google.common.collect.ImmutableList; 23 | import com.huawei.push.util.ValidatorUtils; 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | 27 | import java.io.IOException; 28 | import java.text.MessageFormat; 29 | import java.util.*; 30 | import java.util.concurrent.ScheduledExecutorService; 31 | import java.util.concurrent.ScheduledFuture; 32 | import java.util.concurrent.ThreadFactory; 33 | import java.util.concurrent.TimeUnit; 34 | import java.util.concurrent.atomic.AtomicBoolean; 35 | 36 | /** 37 | * The entry point of Huawei Java SDK. 38 | *

{@link HuaweiApp#initializeApp(HuaweiOption)} initializes the app instance. 39 | */ 40 | public class HuaweiApp { 41 | private static final Logger logger = LoggerFactory.getLogger(HuaweiApp.class); 42 | 43 | private String appId; 44 | private HuaweiOption option; 45 | 46 | /** Global lock */ 47 | private static final Object appsLock = new Object(); 48 | 49 | /** Store a map of */ 50 | private static final Map instances = new HashMap<>(); 51 | 52 | /** HuaweiMessaging can be added in the pattern of service, whcih is designed for Scalability */ 53 | private final Map services = new HashMap<>(); 54 | 55 | private TokenRefresher tokenRefresher; 56 | 57 | private volatile ScheduledExecutorService scheduledExecutor; 58 | 59 | private ThreadManager threadManager; 60 | 61 | private ThreadManager.HuaweiExecutors executors; 62 | 63 | private final AtomicBoolean deleted = new AtomicBoolean(); 64 | 65 | /** lock for synchronizing all internal HuaweiApp state changes */ 66 | private final Object lock = new Object(); 67 | 68 | private HuaweiApp(HuaweiOption option) { 69 | ValidatorUtils.checkArgument(option != null, "HuaweiOption must not be null"); 70 | this.option = option; 71 | this.appId = option.getCredential().getAppId(); 72 | this.tokenRefresher = new TokenRefresher(this); 73 | this.threadManager = option.getThreadManager(); 74 | this.executors = threadManager.getHuaweiExecutors(this); 75 | } 76 | 77 | public HuaweiOption getOption() { 78 | return option; 79 | } 80 | 81 | public String getAppId() { 82 | return appId; 83 | } 84 | 85 | /** 86 | * Returns the instance identified by the unique appId, or throws if it does not exist. 87 | * 88 | * @param appId represents the id of the {@link HuaweiApp} instance. 89 | * @return the {@link HuaweiApp} corresponding to the id. 90 | * @throws IllegalStateException if the {@link HuaweiApp} was not initialized, either via {@link 91 | * #initializeApp(HuaweiOption)} or {@link #getApps()}. 92 | */ 93 | public static HuaweiApp getInstance(HuaweiOption option) { 94 | String appId = option.getCredential().getAppId(); 95 | synchronized (appsLock) { 96 | HuaweiApp app = instances.get(appId); 97 | if (app != null) { 98 | return app; 99 | } 100 | // String errorMessage = MessageFormat.format("HuaweiApp with id {0} doesn't exist", appId); 101 | // throw new IllegalStateException(errorMessage); 102 | return initializeApp(option); 103 | } 104 | } 105 | 106 | /** 107 | * Initializes the {@link HuaweiApp} instance using the given option. 108 | * 109 | * @throws IllegalStateException if the app instance has already been initialized. 110 | */ 111 | public static HuaweiApp initializeApp(HuaweiOption option) { 112 | String appId = option.getCredential().getAppId(); 113 | final HuaweiApp app; 114 | synchronized (appsLock) { 115 | if (!instances.containsKey(appId)) { 116 | ValidatorUtils.checkState(!instances.containsKey(appId), "HuaweiApp with id " + appId + " already exists!"); 117 | app = new HuaweiApp(option); 118 | instances.put(appId, app); 119 | app.startTokenRefresher(); 120 | } else { 121 | app = getInstance(option); 122 | } 123 | 124 | } 125 | return app; 126 | } 127 | 128 | /** Returns a list of all HuaweiApps. */ 129 | public static List getApps() { 130 | synchronized (appsLock) { 131 | return ImmutableList.copyOf(instances.values()); 132 | } 133 | } 134 | 135 | /** 136 | * Get all appIds which are be stored in the instances 137 | */ 138 | public static List getAllAppIds() { 139 | Set allAppIds = new HashSet<>(); 140 | synchronized (appsLock) { 141 | for (HuaweiApp app : instances.values()) { 142 | allAppIds.add(app.getAppId()); 143 | } 144 | } 145 | List sortedIdList = new ArrayList<>(allAppIds); 146 | Collections.sort(sortedIdList); 147 | return sortedIdList; 148 | } 149 | 150 | /** 151 | * Deletes the {@link HuaweiApp} and all its data. All calls to this {@link HuaweiApp} 152 | * instance will throw once it has been called. 153 | * 154 | *

A no-op if delete was called before. 155 | */ 156 | public void delete() { 157 | synchronized (lock) { 158 | boolean valueChanged = deleted.compareAndSet(false /* expected */, true); 159 | if (!valueChanged) { 160 | return; 161 | } 162 | 163 | try { 164 | this.getOption().getHttpClient().close(); 165 | this.getOption().getCredential().getHttpClient().close(); 166 | } catch (IOException e) { 167 | logger.debug("Fail to close httpClient"); 168 | } 169 | 170 | for (HuaweiService service : services.values()) { 171 | service.destroy(); 172 | } 173 | services.clear(); 174 | tokenRefresher.stop(); 175 | 176 | threadManager.releaseHuaweiExecutors(this, executors); 177 | if (scheduledExecutor != null) { 178 | scheduledExecutor.shutdown(); 179 | scheduledExecutor = null; 180 | } 181 | } 182 | 183 | synchronized (appsLock) { 184 | instances.remove(this.getAppId()); 185 | } 186 | } 187 | 188 | /** 189 | * Check the app is not deleted, whcic is the premisi of some methods 190 | */ 191 | private void checkNotDeleted() { 192 | String errorMessage = MessageFormat.format("HuaweiApp with id {0} was deleted", getAppId()); 193 | ValidatorUtils.checkState(!deleted.get(), errorMessage); 194 | } 195 | 196 | /** 197 | * Singleton mode, ensure the scheduleExecutor is singleton 198 | */ 199 | private ScheduledExecutorService singleScheduledExecutorService() { 200 | if (scheduledExecutor == null) { 201 | synchronized (lock) { 202 | checkNotDeleted(); 203 | if (scheduledExecutor == null) { 204 | scheduledExecutor = new HuaweiScheduledExecutor(getThreadFactory(), "huawei-scheduled-worker"); 205 | } 206 | } 207 | } 208 | return scheduledExecutor; 209 | } 210 | 211 | public ThreadFactory getThreadFactory() { 212 | return threadManager.getThreadFactory(); 213 | } 214 | 215 | private ScheduledExecutorService getScheduledExecutorService() { 216 | return singleScheduledExecutorService(); 217 | } 218 | 219 | ScheduledFuture schedule(Runnable runnable, long initialDelay, long period) { 220 | return getScheduledExecutorService().scheduleWithFixedDelay(runnable, initialDelay, period, TimeUnit.MILLISECONDS); 221 | } 222 | 223 | /** 224 | * Add service to the app, such as HuaweiMessaging, other services can be added if needed 225 | */ 226 | void addService(HuaweiService service) { 227 | synchronized (lock) { 228 | checkNotDeleted(); 229 | ValidatorUtils.checkArgument(!services.containsKey(service.getId()), "service already exists"); 230 | services.put(service.getId(), service); 231 | } 232 | } 233 | 234 | HuaweiService getService(String id) { 235 | synchronized (lock) { 236 | return services.get(id); 237 | } 238 | } 239 | 240 | /** 241 | * Start the scheduled task for refreshing token automatically 242 | */ 243 | public void startTokenRefresher() { 244 | synchronized (lock) { 245 | checkNotDeleted(); 246 | tokenRefresher.start(); 247 | } 248 | } 249 | 250 | /** It is just for test */ 251 | public static void clearInstancesForTest() { 252 | synchronized (appsLock) { 253 | //copy before delete 254 | for (HuaweiApp app : ImmutableList.copyOf(instances.values())) { 255 | app.delete(); 256 | } 257 | instances.clear(); 258 | } 259 | } 260 | } 261 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/messaging/HuaweiCredential.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.messaging; 17 | 18 | import com.alibaba.fastjson.JSONObject; 19 | 20 | import org.apache.http.client.methods.CloseableHttpResponse; 21 | import org.apache.http.client.methods.HttpPost; 22 | import org.apache.http.entity.StringEntity; 23 | import org.apache.http.impl.client.CloseableHttpClient; 24 | import org.apache.http.impl.client.HttpClients; 25 | import org.apache.http.util.EntityUtils; 26 | import org.slf4j.Logger; 27 | import org.slf4j.LoggerFactory; 28 | 29 | import java.io.IOException; 30 | import java.text.MessageFormat; 31 | import java.util.ResourceBundle; 32 | import java.util.concurrent.locks.Lock; 33 | import java.util.concurrent.locks.ReentrantLock; 34 | 35 | /** 36 | * Accept the appId and appSecret given by the user and build the credential 37 | * Every app has a credential which is for certification 38 | */ 39 | public class HuaweiCredential { 40 | private static final Logger logger = LoggerFactory.getLogger(HuaweiCredential.class); 41 | 42 | private final String PUSH_AT_URL = ResourceBundle.getBundle("url").getString("token_server"); 43 | 44 | private String appId; 45 | private String appSecret; 46 | 47 | private String accessToken; 48 | private long expireIn; 49 | private Lock lock; 50 | private CloseableHttpClient httpClient; 51 | 52 | private HuaweiCredential(Builder builder) { 53 | this.lock = new ReentrantLock(); 54 | this.appId = builder.appId; 55 | this.appSecret = builder.appSecret; 56 | if (builder.httpClient == null) { 57 | httpClient = HttpClients.createDefault(); 58 | } else { 59 | this.httpClient = builder.httpClient; 60 | } 61 | } 62 | 63 | /** 64 | * Refresh accessToken via HCM manually. 65 | */ 66 | public final void refreshToken() { 67 | try { 68 | executeRefresh(); 69 | } catch (IOException e) { 70 | logger.debug("Fail to refresh token!", e); 71 | } 72 | } 73 | 74 | private void executeRefresh() throws IOException { 75 | String requestBody = createRequestBody(appId, appSecret); 76 | 77 | HttpPost httpPost = new HttpPost(PUSH_AT_URL); 78 | StringEntity entity = new StringEntity(requestBody); 79 | httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); 80 | httpPost.setEntity(entity); 81 | CloseableHttpResponse response = httpClient.execute(httpPost); 82 | String jsonStr = EntityUtils.toString(response.getEntity()); 83 | int statusCode = response.getStatusLine().getStatusCode(); 84 | if (statusCode == 200) { 85 | JSONObject jsonObject = JSONObject.parseObject(jsonStr); 86 | this.accessToken = jsonObject.getString("access_token"); 87 | this.expireIn = jsonObject.getLong("expires_in") * 1000L; 88 | } else { 89 | logger.debug("Fail to refresh token!"); 90 | } 91 | } 92 | 93 | private String createRequestBody(String appId, String appSecret) { 94 | return MessageFormat.format("grant_type=client_credentials&client_secret={0}&client_id={1}", appSecret, appId); 95 | } 96 | 97 | /** 98 | * getter 99 | */ 100 | public final String getAccessToken() { 101 | this.lock.lock(); 102 | 103 | String tmp; 104 | try { 105 | tmp = this.accessToken; 106 | } finally { 107 | this.lock.unlock(); 108 | } 109 | 110 | return tmp; 111 | } 112 | 113 | public final long getExpireIn() { 114 | this.lock.lock(); 115 | 116 | long tmp; 117 | try { 118 | tmp = this.expireIn; 119 | } finally { 120 | this.lock.unlock(); 121 | } 122 | 123 | return tmp; 124 | } 125 | 126 | protected CloseableHttpClient getHttpClient() { 127 | return httpClient; 128 | } 129 | 130 | public String getAppId() { 131 | return appId; 132 | } 133 | 134 | /** 135 | * Builder for constructing {@link HuaweiCredential}. 136 | */ 137 | public static Builder builder() { 138 | return new Builder(); 139 | } 140 | 141 | public static class Builder { 142 | private String appId; 143 | private String appSecret; 144 | 145 | private CloseableHttpClient httpClient; 146 | 147 | private Builder() { 148 | } 149 | 150 | public Builder setAppId(String appId) { 151 | this.appId = appId; 152 | return this; 153 | } 154 | 155 | public Builder setAppSecret(String appSecret) { 156 | this.appSecret = appSecret; 157 | return this; 158 | } 159 | 160 | public Builder setHttpClient(CloseableHttpClient httpClient) { 161 | this.httpClient = httpClient; 162 | return this; 163 | } 164 | 165 | public HuaweiCredential build() { 166 | return new HuaweiCredential(this); 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/messaging/HuaweiMessageClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.messaging; 17 | 18 | import com.huawei.push.exception.HuaweiMesssagingException; 19 | import com.huawei.push.message.Message; 20 | import com.huawei.push.message.TopicMessage; 21 | import com.huawei.push.reponse.SendResponse; 22 | 23 | /** 24 | * sending messages interface 25 | */ 26 | public interface HuaweiMessageClient { 27 | 28 | /** 29 | * Sends the given message with HCM. 30 | * 31 | * @param message message {@link Message} 32 | * @param validateOnly A boolean indicating whether to send message for test. or not. 33 | * @return {@link SendResponse}. 34 | * @throws HuaweiMesssagingException 35 | */ 36 | SendResponse send(Message message, boolean validateOnly, String accessToken) throws HuaweiMesssagingException; 37 | 38 | SendResponse send(TopicMessage message, String operation, String accessToken) throws HuaweiMesssagingException; 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/messaging/HuaweiMessageClientImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.messaging; 17 | 18 | import com.alibaba.fastjson.JSON; 19 | import com.alibaba.fastjson.JSONArray; 20 | import com.alibaba.fastjson.JSONObject; 21 | import com.huawei.push.exception.HuaweiMesssagingException; 22 | import com.huawei.push.message.Message; 23 | import com.huawei.push.message.TopicMessage; 24 | import com.huawei.push.model.TopicOperation; 25 | import com.huawei.push.reponse.SendResponse; 26 | import com.huawei.push.reponse.TopicListResponse; 27 | import com.huawei.push.reponse.TopicSendResponse; 28 | import com.huawei.push.util.ValidatorUtils; 29 | import org.apache.commons.lang3.StringUtils; 30 | import org.apache.http.client.HttpResponseException; 31 | import org.apache.http.client.methods.CloseableHttpResponse; 32 | import org.apache.http.client.methods.HttpPost; 33 | import org.apache.http.entity.StringEntity; 34 | import org.apache.http.impl.client.CloseableHttpClient; 35 | import org.apache.http.util.EntityUtils; 36 | 37 | import java.io.IOException; 38 | import java.text.MessageFormat; 39 | import java.util.HashMap; 40 | import java.util.Map; 41 | import java.util.ResourceBundle; 42 | 43 | public class HuaweiMessageClientImpl implements HuaweiMessageClient { 44 | private static final String PUSH_URL = ResourceBundle.getBundle("url").getString("push_open_url"); 45 | 46 | private final String HcmPushUrl; 47 | private String hcmTopicUrl; 48 | private String hcmGroupUrl; 49 | private String hcmTokenUrl; 50 | private final CloseableHttpClient httpClient; 51 | 52 | private HuaweiMessageClientImpl(Builder builder) { 53 | this.HcmPushUrl = MessageFormat.format(PUSH_URL + "/v1/{0}/messages:send", builder.appId); 54 | this.hcmTopicUrl = MessageFormat.format(PUSH_URL + "/v1/{0}/topic:{1}", builder.appId); 55 | 56 | ValidatorUtils.checkArgument(builder.httpClient != null, "requestFactory must not be null"); 57 | this.httpClient = builder.httpClient; 58 | } 59 | 60 | /** 61 | * getter 62 | */ 63 | public String getHcmSendUrl() { 64 | return HcmPushUrl; 65 | } 66 | 67 | public CloseableHttpClient getHttpClient() { 68 | return httpClient; 69 | } 70 | 71 | @Override 72 | public SendResponse send(Message message, boolean validateOnly, String accessToken) throws HuaweiMesssagingException { 73 | try { 74 | return sendRequest(message, validateOnly, accessToken); 75 | } catch (IOException e) { 76 | throw new HuaweiMesssagingException(HuaweiMessaging.INTERNAL_ERROR, "Error while calling HCM backend service", e); 77 | } 78 | } 79 | 80 | @Override 81 | public SendResponse send(TopicMessage message, String operation, String accessToken) throws HuaweiMesssagingException { 82 | try { 83 | return sendRequest(message, operation, accessToken); 84 | } catch (IOException e) { 85 | throw new HuaweiMesssagingException(HuaweiMessaging.INTERNAL_ERROR, "Error while calling HCM backend service", e); 86 | } 87 | } 88 | 89 | private SendResponse sendRequest(TopicMessage message, String operation, String accessToken) throws IOException, HuaweiMesssagingException { 90 | this.hcmTopicUrl = MessageFormat.format(hcmTopicUrl, "", operation); 91 | HttpPost httpPost = new HttpPost(this.hcmTopicUrl); 92 | StringEntity entity = new StringEntity(JSON.toJSONString(message), "UTF-8"); 93 | httpPost.setHeader("Authorization", "Bearer " + accessToken); 94 | httpPost.setHeader("Content-Type", "application/json;charset=utf-8"); 95 | httpPost.setEntity(entity); 96 | CloseableHttpResponse response = httpClient.execute(httpPost); 97 | String rpsContent = EntityUtils.toString(response.getEntity()); 98 | int statusCode = response.getStatusLine().getStatusCode(); 99 | if (statusCode == 200) { 100 | JSONObject jsonObject = JSONObject.parseObject(rpsContent); 101 | String code = jsonObject.getString("code"); 102 | String msg = jsonObject.getString("msg"); 103 | String requestId = jsonObject.getString("requestId"); 104 | if (StringUtils.equals(code, "80000000")) { 105 | SendResponse sendResponse; 106 | if (StringUtils.equals(operation, TopicOperation.LIST.getValue())) { 107 | JSONArray topics = jsonObject.getJSONArray("topics"); 108 | sendResponse = TopicListResponse.fromCode(code, msg, requestId, topics); 109 | } else { 110 | Integer failureCount = jsonObject.getInteger("failureCount"); 111 | Integer successCount = jsonObject.getInteger("successCount"); 112 | JSONArray errors = jsonObject.getJSONArray("errors"); 113 | sendResponse = TopicSendResponse.fromCode(code, msg, requestId, failureCount, successCount, errors); 114 | } 115 | return sendResponse; 116 | } else { 117 | String errorMsg = MessageFormat.format("error code : {0}, error message : {1}", String.valueOf(code), msg); 118 | throw new HuaweiMesssagingException(HuaweiMessaging.KNOWN_ERROR, errorMsg); 119 | } 120 | } 121 | HttpResponseException exception = new HttpResponseException(statusCode, rpsContent); 122 | throw createExceptionFromResponse(exception); 123 | } 124 | 125 | /** 126 | * send request 127 | * 128 | * @param message message {@link Message} 129 | * @param validateOnly A boolean indicating whether to send message for test or not. 130 | * @param accessToken A String for oauth 131 | * @return {@link SendResponse} 132 | * @throws IOException If a error occurs when sending request 133 | */ 134 | private SendResponse sendRequest(Message message, boolean validateOnly, String accessToken) throws IOException, HuaweiMesssagingException { 135 | Map map = createRequestMap(message, validateOnly); 136 | HttpPost httpPost = new HttpPost(this.HcmPushUrl); 137 | StringEntity entity = new StringEntity(JSON.toJSONString(map), "UTF-8"); 138 | // String aqa = JSON.toJSONString(map); 139 | httpPost.setHeader("Authorization", "Bearer " + accessToken); 140 | httpPost.setHeader("Content-Type", "application/json;charset=utf-8"); 141 | httpPost.setEntity(entity); 142 | CloseableHttpResponse response = httpClient.execute(httpPost); 143 | String rpsContent = EntityUtils.toString(response.getEntity()); 144 | int statusCode = response.getStatusLine().getStatusCode(); 145 | if (statusCode == 200) { 146 | JSONObject jsonObject = JSONObject.parseObject(rpsContent); 147 | String code = jsonObject.getString("code"); 148 | String msg = jsonObject.getString("msg"); 149 | String requestId = jsonObject.getString("requestId"); 150 | if (StringUtils.equals(code, "80000000")) { 151 | return SendResponse.fromCode(code, msg, requestId); 152 | } else { 153 | String errorMsg = MessageFormat.format("error code : {0}, error message : {1}", String.valueOf(code), msg); 154 | throw new HuaweiMesssagingException(HuaweiMessaging.KNOWN_ERROR, errorMsg); 155 | } 156 | } 157 | HttpResponseException exception = new HttpResponseException(statusCode, rpsContent); 158 | throw createExceptionFromResponse(exception); 159 | } 160 | 161 | /** 162 | * create the map of the request body, mostly for wrapping the message with validate_only 163 | * 164 | * @param message A non-null {@link Message} to be sent. 165 | * @param validateOnly A boolean indicating whether to send message for test or not. 166 | * @return a map of request 167 | */ 168 | private Map createRequestMap(Message message, boolean validateOnly) { 169 | return new HashMap() { 170 | { 171 | put("validate_only", validateOnly); 172 | put("message", message); 173 | } 174 | }; 175 | } 176 | 177 | private HuaweiMesssagingException createExceptionFromResponse(HttpResponseException e) { 178 | String msg = MessageFormat.format("Unexpected HTTP response with status : {0}, body : {1}", e.getStatusCode(), e.getMessage()); 179 | return new HuaweiMesssagingException(HuaweiMessaging.UNKNOWN_ERROR, msg, e); 180 | } 181 | 182 | static HuaweiMessageClientImpl fromApp(HuaweiApp app) { 183 | String appId = ImplHuaweiTrampolines.getAppId(app); 184 | return HuaweiMessageClientImpl.builder() 185 | .setAppId(appId) 186 | .setHttpClient(app.getOption().getHttpClient()) 187 | .build(); 188 | } 189 | 190 | static Builder builder() { 191 | return new Builder(); 192 | } 193 | 194 | static final class Builder { 195 | 196 | private String appId; 197 | private CloseableHttpClient httpClient; 198 | 199 | private Builder() { 200 | } 201 | 202 | public Builder setAppId(String appId) { 203 | this.appId = appId; 204 | return this; 205 | } 206 | 207 | public Builder setHttpClient(CloseableHttpClient httpClient) { 208 | this.httpClient = httpClient; 209 | return this; 210 | } 211 | 212 | public HuaweiMessageClientImpl build() { 213 | return new HuaweiMessageClientImpl(this); 214 | } 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/messaging/HuaweiMessaging.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.messaging; 17 | 18 | import com.google.common.base.Supplier; 19 | import com.google.common.base.Suppliers; 20 | import com.huawei.push.exception.HuaweiMesssagingException; 21 | import com.huawei.push.message.Message; 22 | import com.huawei.push.message.TopicMessage; 23 | import com.huawei.push.model.TopicOperation; 24 | import com.huawei.push.reponse.SendResponse; 25 | import com.huawei.push.util.ValidatorUtils; 26 | 27 | import org.slf4j.Logger; 28 | import org.slf4j.LoggerFactory; 29 | 30 | /** 31 | * This class is the entrance for all server-side HCM actions. 32 | * 33 | *

You can get a instance of {@link com.huawei.push.messaging.HuaweiMessaging} 34 | * by a instance of {@link com.huawei.push.messaging.HuaweiApp}, and then use it to send a message 35 | */ 36 | public class HuaweiMessaging { 37 | private static final Logger logger = LoggerFactory.getLogger(HuaweiMessaging.class); 38 | 39 | static final String INTERNAL_ERROR = "internal error"; 40 | 41 | static final String UNKNOWN_ERROR = "unknown error"; 42 | 43 | static final String KNOWN_ERROR = "known error"; 44 | 45 | private final HuaweiApp app; 46 | private final Supplier messagingClient; 47 | 48 | private HuaweiMessaging(Builder builder) { 49 | this.app = builder.app; 50 | this.messagingClient = Suppliers.memoize(builder.messagingClient); 51 | } 52 | 53 | /** 54 | * Gets the {@link HuaweiMessaging} instance for the specified {@link HuaweiApp}. 55 | * 56 | * @return The {@link HuaweiMessaging} instance for the specified {@link HuaweiApp}. 57 | */ 58 | public static synchronized HuaweiMessaging getInstance(HuaweiApp app) { 59 | HuaweiMessagingService service = ImplHuaweiTrampolines.getService(app, SERVICE_ID, HuaweiMessagingService.class); 60 | if (service == null) { 61 | service = ImplHuaweiTrampolines.addService(app, new HuaweiMessagingService(app)); 62 | } 63 | return service.getInstance(); 64 | } 65 | 66 | private static HuaweiMessaging fromApp(final HuaweiApp app) { 67 | return HuaweiMessaging.builder() 68 | .setApp(app) 69 | .setMessagingClient(() -> HuaweiMessageClientImpl.fromApp(app)) 70 | .build(); 71 | } 72 | 73 | HuaweiMessageClient getMessagingClient() { 74 | return messagingClient.get(); 75 | } 76 | 77 | /** 78 | * Sends the given {@link Message} via HCM. 79 | * 80 | * @param message A non-null {@link Message} to be sent. 81 | * @return {@link SendResponse}. 82 | * @throws HuaweiMesssagingException If an error occurs while handing the message off to HCM for 83 | * delivery. 84 | */ 85 | public SendResponse sendMessage(Message message) throws HuaweiMesssagingException { 86 | return sendMessage(message, false); 87 | } 88 | 89 | /** 90 | * @param topicMessage topicmessage 91 | * @return topic subscribe response 92 | * @throws HuaweiMesssagingException 93 | */ 94 | public SendResponse subscribeTopic(TopicMessage topicMessage) throws HuaweiMesssagingException { 95 | final HuaweiMessageClient messagingClient = getMessagingClient(); 96 | return messagingClient.send(topicMessage, TopicOperation.SUBSCRIBE.getValue(), ImplHuaweiTrampolines.getAccessToken(app)); 97 | } 98 | 99 | /** 100 | * @param topicMessage topic Message 101 | * @return topic unsubscribe response 102 | * @throws HuaweiMesssagingException 103 | */ 104 | public SendResponse unsubscribeTopic(TopicMessage topicMessage) throws HuaweiMesssagingException { 105 | final HuaweiMessageClient messagingClient = getMessagingClient(); 106 | return messagingClient.send(topicMessage, TopicOperation.UNSUBSCRIBE.getValue(), ImplHuaweiTrampolines.getAccessToken(app)); 107 | } 108 | 109 | /** 110 | * @param topicMessage topic Message 111 | * @return topic list 112 | * @throws HuaweiMesssagingException 113 | */ 114 | public SendResponse listTopic(TopicMessage topicMessage) throws HuaweiMesssagingException { 115 | final HuaweiMessageClient messagingClient = getMessagingClient(); 116 | return messagingClient.send(topicMessage, TopicOperation.LIST.getValue(), ImplHuaweiTrampolines.getAccessToken(app)); 117 | } 118 | 119 | 120 | /** 121 | * Sends message {@link Message} 122 | * 123 | *

If the {@code validateOnly} option is set to true, the message will not be actually sent. Instead 124 | * HCM performs all the necessary validations, and emulates the send operation. 125 | * 126 | * @param message message {@link Message} to be sent. 127 | * @param validateOnly a boolean indicating whether to send message for test or not. 128 | * @return {@link SendResponse}. 129 | * @throws HuaweiMesssagingException exception. 130 | */ 131 | public SendResponse sendMessage(Message message, boolean validateOnly) throws HuaweiMesssagingException { 132 | ValidatorUtils.checkArgument(message != null, "message must not be null"); 133 | final HuaweiMessageClient messagingClient = getMessagingClient(); 134 | return messagingClient.send(message, validateOnly, ImplHuaweiTrampolines.getAccessToken(app)); 135 | } 136 | 137 | /** 138 | * HuaweiMessagingService 139 | */ 140 | private static final String SERVICE_ID = HuaweiMessaging.class.getName(); 141 | 142 | private static class HuaweiMessagingService extends HuaweiService { 143 | 144 | HuaweiMessagingService(HuaweiApp app) { 145 | super(SERVICE_ID, HuaweiMessaging.fromApp(app)); 146 | } 147 | 148 | @Override 149 | public void destroy() { 150 | 151 | } 152 | } 153 | 154 | /** 155 | * Builder for constructing {@link HuaweiMessaging}. 156 | */ 157 | static Builder builder() { 158 | return new Builder(); 159 | } 160 | 161 | static class Builder { 162 | private HuaweiApp app; 163 | private Supplier messagingClient; 164 | 165 | private Builder() { 166 | } 167 | 168 | public Builder setApp(HuaweiApp app) { 169 | this.app = app; 170 | return this; 171 | } 172 | 173 | public Builder setMessagingClient(Supplier messagingClient) { 174 | this.messagingClient = messagingClient; 175 | return this; 176 | } 177 | 178 | public HuaweiMessaging build() { 179 | return new HuaweiMessaging(this); 180 | } 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/messaging/HuaweiOption.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.messaging; 17 | 18 | import com.huawei.push.util.IgnoreSSLUtils; 19 | import com.huawei.push.util.ValidatorUtils; 20 | import org.apache.http.impl.client.CloseableHttpClient; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | import java.security.KeyManagementException; 25 | import java.security.NoSuchAlgorithmException; 26 | 27 | /** Configurable HCM options. */ 28 | public class HuaweiOption { 29 | private static final Logger logger = LoggerFactory.getLogger(HuaweiOption.class); 30 | 31 | private final HuaweiCredential credential; 32 | private final CloseableHttpClient httpClient; 33 | private final ThreadManager threadManager; 34 | 35 | private HuaweiOption(HuaweiOption.Builder builder) { 36 | ValidatorUtils.checkArgument(builder.credential != null, "HuaweiOption must be initialized with setCredential()"); 37 | this.credential = builder.credential; 38 | 39 | ValidatorUtils.checkArgument(builder.httpClient != null, "HuaweiOption must be initialized with a non-null httpClient"); 40 | this.httpClient = builder.httpClient; 41 | 42 | ValidatorUtils.checkArgument(builder.threadManager != null, "HuaweiOption must be initialized with a non-null threadManager"); 43 | this.threadManager = builder.threadManager; 44 | } 45 | 46 | /** 47 | * Returns a instance of HuaweiCredential used for refreshing token. 48 | * 49 | * @return A HuaweiCredential instance. 50 | */ 51 | public HuaweiCredential getCredential() { 52 | return credential; 53 | } 54 | 55 | /** 56 | * Returns a instance of httpclient used for sending http request. 57 | * 58 | * @return A httpclient instance. 59 | */ 60 | public CloseableHttpClient getHttpClient() { 61 | return httpClient; 62 | } 63 | 64 | public ThreadManager getThreadManager() { 65 | return threadManager; 66 | } 67 | 68 | /** 69 | * Builder for constructing {@link HuaweiOption}. 70 | */ 71 | public static Builder builder() { 72 | return new Builder(); 73 | } 74 | 75 | public static final class Builder { 76 | private HuaweiCredential credential; 77 | private CloseableHttpClient httpClient; 78 | 79 | { 80 | try { 81 | httpClient = IgnoreSSLUtils.createClient(); 82 | } catch (KeyManagementException | NoSuchAlgorithmException e) { 83 | logger.debug("Fail to create httpClient for sending message", e); 84 | } 85 | } 86 | 87 | private ThreadManager threadManager = HuaweiThreadManager.DEFAULT_THREAD_MANAGER; 88 | 89 | 90 | public Builder() {} 91 | 92 | public Builder setCredential(HuaweiCredential credential) { 93 | this.credential = credential; 94 | return this; 95 | } 96 | 97 | public Builder setHttpClient(CloseableHttpClient httpClient) { 98 | this.httpClient = httpClient; 99 | return this; 100 | } 101 | 102 | public Builder setThreadManager(ThreadManager threadManager) { 103 | this.threadManager = threadManager; 104 | return this; 105 | } 106 | 107 | public HuaweiOption build() { 108 | return new HuaweiOption(this); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/messaging/HuaweiScheduledExecutor.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2017 Google Inc. 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | 15 | * 2019.12.15-Changed constructor HuaweiScheduledExecutor 16 | * Huawei Technologies Co., Ltd. 17 | * 18 | */ 19 | package com.huawei.push.messaging; 20 | 21 | import com.google.common.base.Strings; 22 | import com.google.common.util.concurrent.ThreadFactoryBuilder; 23 | 24 | import java.util.concurrent.ScheduledThreadPoolExecutor; 25 | import java.util.concurrent.ThreadFactory; 26 | 27 | import static com.google.common.base.Preconditions.checkArgument; 28 | 29 | /** 30 | * A single-threaded scheduled executor implementation. 31 | */ 32 | public class HuaweiScheduledExecutor extends ScheduledThreadPoolExecutor { 33 | 34 | public HuaweiScheduledExecutor(ThreadFactory threadFactory, String name) { 35 | this(threadFactory, name, null); 36 | } 37 | 38 | public HuaweiScheduledExecutor(ThreadFactory threadFactory, String name, Thread.UncaughtExceptionHandler handler) { 39 | super(1, decorateThreadFactory(threadFactory, name, handler)); 40 | setRemoveOnCancelPolicy(true); 41 | } 42 | 43 | static ThreadFactory getThreadFactoryWithName(ThreadFactory threadFactory, String name) { 44 | return decorateThreadFactory(threadFactory, name, null); 45 | } 46 | 47 | private static ThreadFactory decorateThreadFactory( 48 | ThreadFactory threadFactory, String name, Thread.UncaughtExceptionHandler handler) { 49 | checkArgument(!Strings.isNullOrEmpty(name)); 50 | ThreadFactoryBuilder builder = new ThreadFactoryBuilder() 51 | .setThreadFactory(threadFactory) 52 | .setNameFormat(name) 53 | .setDaemon(true); 54 | if (handler != null) { 55 | builder.setUncaughtExceptionHandler(handler); 56 | } 57 | return builder.build(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/messaging/HuaweiService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.messaging; 17 | 18 | /** 19 | * the services exposed from the HCM SDK 20 | * Each instance of the class is associated with one instance of the HuaweiApp 21 | */ 22 | public abstract class HuaweiService { 23 | private String id; 24 | protected T instance; 25 | 26 | protected HuaweiService(String id, T instance) { 27 | this.id = id; 28 | this.instance = instance; 29 | } 30 | 31 | public String getId() { 32 | return id; 33 | } 34 | 35 | public T getInstance() { 36 | return instance; 37 | } 38 | 39 | public abstract void destroy(); 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/messaging/HuaweiThreadManager.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2017 Google Inc. 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | 15 | * 2019.12.15-Changed method releaseExecutor 16 | * Huawei Technologies Co., Ltd. 17 | * 18 | */ 19 | package com.huawei.push.messaging; 20 | 21 | import java.util.HashSet; 22 | import java.util.Set; 23 | import java.util.concurrent.ExecutorService; 24 | import java.util.concurrent.Executors; 25 | import java.util.concurrent.ThreadFactory; 26 | 27 | 28 | /** Default ThreadManager implementations used by the HCM SDK */ 29 | public class HuaweiThreadManager { 30 | 31 | public static final ThreadManager DEFAULT_THREAD_MANAGER = new DefaultThreadManager(); 32 | 33 | /** 34 | * An abstract ThreadManager implementation that uses the same executor service 35 | * across all active apps. The executor service is initialized when the first app is initialized, 36 | * and terminated when the last app is deleted. This class is thread safe. 37 | */ 38 | abstract static class GlobalThreadManager extends ThreadManager { 39 | private final Object lock = new Object(); 40 | private final Set apps = new HashSet<>(); 41 | private ExecutorService executorService; 42 | 43 | @Override 44 | protected ExecutorService getExecutor(HuaweiApp app) { 45 | synchronized (lock) { 46 | if (executorService == null) { 47 | executorService = doInit(); 48 | } 49 | apps.add(app.getOption().getCredential().getAppId()); 50 | return executorService; 51 | } 52 | } 53 | 54 | @Override 55 | protected void releaseExecutor(HuaweiApp app, ExecutorService executor) { 56 | synchronized (lock) { 57 | String appId = app.getOption().getCredential().getAppId(); 58 | if (apps.remove(appId) && apps.isEmpty()) { 59 | doCleanup(executorService); 60 | executorService = null; 61 | } 62 | } 63 | } 64 | 65 | /** 66 | * Initializes the executor service. Called when the first application is initialized. 67 | */ 68 | protected abstract ExecutorService doInit(); 69 | 70 | /** 71 | * Cleans up the executor service. Called when the last application is deleted. 72 | */ 73 | protected abstract void doCleanup(ExecutorService executorService); 74 | } 75 | 76 | private static class DefaultThreadManager extends GlobalThreadManager { 77 | 78 | @Override 79 | protected ExecutorService doInit() { 80 | ThreadFactory threadFactory = HuaweiScheduledExecutor.getThreadFactoryWithName(getThreadFactory(), "huawei-default-%d"); 81 | return Executors.newCachedThreadPool(threadFactory); 82 | } 83 | 84 | @Override 85 | protected void doCleanup(ExecutorService executorService) { 86 | executorService.shutdown(); 87 | } 88 | 89 | @Override 90 | protected ThreadFactory getThreadFactory() { 91 | return Executors.defaultThreadFactory(); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/messaging/ImplHuaweiTrampolines.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2017 Google Inc. 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | 15 | * 2019.12.15-added method getAccessToken 16 | * Huawei Technologies Co., Ltd. 17 | * 18 | */ 19 | package com.huawei.push.messaging; 20 | 21 | import org.apache.http.client.HttpClient; 22 | 23 | /** 24 | * Provides trampolines into package-private APIs used by components of HCM 25 | */ 26 | public final class ImplHuaweiTrampolines { 27 | private ImplHuaweiTrampolines() {} 28 | 29 | public static HuaweiCredential getCredential(HuaweiApp app) { 30 | return app.getOption().getCredential(); 31 | } 32 | 33 | public static String getAccessToken(HuaweiApp app) { 34 | return app.getOption().getCredential().getAccessToken(); 35 | } 36 | 37 | public static String getAppId(HuaweiApp app) { 38 | return app.getOption().getCredential().getAppId(); 39 | } 40 | 41 | public static HttpClient getHttpClient(HuaweiApp app) { 42 | return app.getOption().getHttpClient(); 43 | } 44 | 45 | public static T getService(HuaweiApp app, String id, Class type) { 46 | return type.cast(app.getService(id)); 47 | } 48 | 49 | public static T addService(HuaweiApp app, T service) { 50 | app.addService(service); 51 | return service; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/messaging/ThreadManager.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2017 Google Inc. 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | 15 | * 2019.12.15-changed method getHuaweiExecutors 16 | * 2019.12.15-changed method releaseHuaweiExecutors 17 | * 2019.12.15-changed method getExecutor 18 | * 2019.12.15-changed method releaseExecutor 19 | * Huawei Technologies Co., Ltd. 20 | * 21 | */ 22 | package com.huawei.push.messaging; 23 | 24 | import com.huawei.push.util.ValidatorUtils; 25 | 26 | import java.util.concurrent.ExecutorService; 27 | import java.util.concurrent.ThreadFactory; 28 | 29 | /** 30 | * An interface that controls the thread pools and thread factories used by the HCM SDK. Each 31 | * instance of HuaweiApp uses an implementation of this interface to create and manage 32 | * threads. 33 | */ 34 | public abstract class ThreadManager { 35 | final HuaweiExecutors getHuaweiExecutors(HuaweiApp app) { 36 | return new HuaweiExecutors(getExecutor(app)); 37 | } 38 | 39 | final void releaseHuaweiExecutors(HuaweiApp app, HuaweiExecutors executor) { 40 | releaseExecutor(app, executor.userExecutor); 41 | } 42 | 43 | /** 44 | * Returns the main thread pool for an app. 45 | * 46 | * @param app A {@link HuaweiApp} instance. 47 | * @return A non-null ExecutorService instance. 48 | */ 49 | protected abstract ExecutorService getExecutor(HuaweiApp app); 50 | 51 | /** 52 | * Cleans up the thread pool associated with an app. 53 | * This method is invoked when an app is deleted. 54 | * 55 | * @param app A {@link HuaweiApp} instance. 56 | * @return A non-null ExecutorService instance. 57 | */ 58 | protected abstract void releaseExecutor(HuaweiApp app, ExecutorService executor); 59 | 60 | /** 61 | * Returns the ThreadFactory to be used for creating long-lived threads. This is 62 | * used mainly to create the long-lived worker threads for the scheduled (periodic) tasks started by the SDK. 63 | * The SDK guarantees clean termination of all threads started via this ThreadFactory, when the user 64 | * calls {@link HuaweiApp#delete()}. 65 | * 66 | *

If long-lived threads cannot be supported in the current runtime, this method may 67 | * throw a {@code RuntimeException}. 68 | * 69 | * @return A non-null ThreadFactory. 70 | */ 71 | protected abstract ThreadFactory getThreadFactory(); 72 | 73 | static final class HuaweiExecutors { 74 | private ExecutorService userExecutor; 75 | 76 | private HuaweiExecutors(ExecutorService userExecutor) { 77 | ValidatorUtils.checkArgument(userExecutor != null, "ExecutorService must not be null"); 78 | this.userExecutor = userExecutor; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/messaging/TokenRefresher.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2017 Google Inc. 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | 15 | * 2019.12.15-changed constructor TokenRefresher 16 | * Huawei Technologies Co., Ltd. 17 | * 18 | */ 19 | package com.huawei.push.messaging; 20 | 21 | import com.huawei.push.util.ValidatorUtils; 22 | import org.apache.commons.lang3.StringUtils; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | 26 | import java.util.concurrent.Future; 27 | 28 | /** 29 | * Utility class for scheduling proactive token refresh events. Each HuaweiApp should have 30 | * its own instance of this class. TokenRefresher schedules token refresh events when token is expired. 31 | * 32 | *

This class is thread safe. It will handle only one token change event at a time. It also 33 | * cancels any pending token refresh events, before scheduling a new one. 34 | */ 35 | public class TokenRefresher { 36 | private static final Logger logger = LoggerFactory.getLogger(TokenRefresher.class); 37 | 38 | private HuaweiApp app; 39 | private HuaweiCredential credential; 40 | 41 | private Future future; 42 | 43 | public TokenRefresher(HuaweiApp app) { 44 | ValidatorUtils.checkArgument(app != null, "app must not be null"); 45 | this.app = app; 46 | this.credential = app.getOption().getCredential(); 47 | } 48 | 49 | protected void scheduleNext(Runnable task, long initialDelay, long period) { 50 | logger.debug("Scheduling next token refresh in {} milliseconds", period); 51 | try { 52 | future = app.schedule(task, initialDelay, period); 53 | } catch (UnsupportedOperationException e) { 54 | logger.debug("Failed to schedule token refresh event", e); 55 | } 56 | } 57 | 58 | /** 59 | * Schedule a forced token refresh to be executed after a specified period. 60 | * 61 | * @param period in milliseconds, after which the token should be forcibly refreshed. 62 | */ 63 | public void scheduleRefresh(final long period) { 64 | cancelPrevious(); 65 | scheduleNext(() -> credential.refreshToken(), period, period); 66 | } 67 | 68 | private void cancelPrevious() { 69 | if (future != null) { 70 | future.cancel(true); 71 | } 72 | } 73 | 74 | /** 75 | * Starts the TokenRefresher if not already started. Starts refreshing when token is expired. If no active 76 | * token is present, or if the available token is expired soon, this will also refresh immediately. 77 | */ 78 | final synchronized void start() { 79 | logger.debug("Starting the proactive token refresher"); 80 | String accessToken = credential.getAccessToken(); 81 | long refreshDelay; 82 | if (accessToken == null || StringUtils.isEmpty(accessToken)) { 83 | credential.refreshToken(); 84 | } 85 | 86 | refreshDelay = credential.getExpireIn(); 87 | 88 | scheduleRefresh(refreshDelay); 89 | } 90 | 91 | final synchronized void stop() { 92 | cancelPrevious(); 93 | logger.debug("Stopped the proactive token refresher"); 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/model/Importance.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.model; 17 | 18 | public enum Importance { 19 | /** 20 | * LOW 21 | */ 22 | LOW("LOW"), 23 | 24 | /** 25 | * NORMAL 26 | */ 27 | NORMAL("NORMAL"), 28 | 29 | /** 30 | * HIGH 31 | */ 32 | HIGH("HIGH"); 33 | 34 | private String value; 35 | 36 | private Importance(String value) { 37 | this.value = value; 38 | } 39 | 40 | /** 41 | * Gets value * 42 | * 43 | * @return the value 44 | */ 45 | public String getValue() { 46 | return value; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/model/TopicOperation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.model; 17 | 18 | public enum TopicOperation { 19 | SUBSCRIBE("subscribe"), 20 | UNSUBSCRIBE("unsubscribe"), 21 | LIST("list"); 22 | 23 | private String value; 24 | 25 | private TopicOperation(String value) { 26 | this.value = value; 27 | } 28 | 29 | /** 30 | * Gets value * 31 | * 32 | * @return the value 33 | */ 34 | public String getValue() { 35 | return value; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/model/Urgency.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.model; 17 | 18 | public enum Urgency { 19 | HIGH("HIGH"), 20 | NORMAL("NORMAL"); 21 | 22 | private String value; 23 | 24 | private Urgency(String value) { 25 | this.value = value; 26 | } 27 | 28 | /** 29 | * Gets value * 30 | * 31 | * @return the value 32 | */ 33 | public String getValue() { 34 | return value; 35 | } 36 | } -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/model/Visibility.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.model; 17 | 18 | public enum Visibility { 19 | VISIBILITY_UNSPECIFIED("VISIBILITY_UNSPECIFIED"), 20 | PRIVATE("PRIVATE"), 21 | PUBLIC("PUBLIC"), 22 | SECRET("SECRET"); 23 | 24 | private String value; 25 | 26 | private Visibility(String value) { 27 | this.value = value; 28 | } 29 | 30 | /** 31 | * Gets value * 32 | * 33 | * @return the value 34 | */ 35 | public String getValue() { 36 | return value; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/reponse/SendResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.reponse; 17 | 18 | /** 19 | * A class of reponse which exposed to developer 20 | */ 21 | public class SendResponse { 22 | private final String code; 23 | private final String msg; 24 | private final String requestId; 25 | 26 | 27 | protected SendResponse(String coede, String msg, String requestId) { 28 | this.code = coede; 29 | this.msg = msg; 30 | this.requestId = requestId; 31 | } 32 | 33 | public String getCode() { 34 | return code; 35 | } 36 | 37 | public String getMsg() { 38 | return msg; 39 | } 40 | 41 | public String getRequestId() { 42 | return requestId; 43 | } 44 | 45 | public static SendResponse fromCode(String coede, String msg, String requestId) { 46 | return new SendResponse(coede, msg, requestId); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/reponse/TopicListResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.reponse; 17 | 18 | import com.alibaba.fastjson.JSONArray; 19 | 20 | public class TopicListResponse extends SendResponse { 21 | private final JSONArray topics; 22 | 23 | public JSONArray getTopics() { 24 | return topics; 25 | } 26 | 27 | private TopicListResponse(String code, String msg, String requestId, JSONArray topics) { 28 | super(code, msg, requestId); 29 | this.topics = topics; 30 | } 31 | 32 | public static TopicListResponse fromCode(String code, String msg, String requestId, JSONArray topics) { 33 | return new TopicListResponse(code, msg, requestId, topics); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/reponse/TopicSendResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.reponse; 17 | 18 | import com.alibaba.fastjson.JSONArray; 19 | 20 | public final class TopicSendResponse extends SendResponse { 21 | private final Integer failureCount; 22 | private final Integer successCount; 23 | private final JSONArray errors; 24 | 25 | public Integer getFailureCount() { 26 | return failureCount; 27 | } 28 | 29 | public Integer getSuccessCount() { 30 | return successCount; 31 | } 32 | 33 | public JSONArray getErrors() { 34 | return errors; 35 | } 36 | 37 | private TopicSendResponse(String code, String msg, String requestId, Integer failureCount, Integer successCount, JSONArray errors) { 38 | super(code,msg,requestId); 39 | this.failureCount = failureCount; 40 | this.successCount = successCount; 41 | this.errors = errors; 42 | } 43 | 44 | public static TopicSendResponse fromCode(String code, String msg, String requestId,Integer failureCount,Integer successCount,JSONArray errors ) { 45 | return new TopicSendResponse(code, msg, requestId,failureCount,successCount,errors); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/util/CollectionUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.util; 17 | 18 | import java.util.Collection; 19 | import java.util.Map; 20 | 21 | /** 22 | * A tool for processing collections 23 | */ 24 | public class CollectionUtils { 25 | public CollectionUtils() { 26 | } 27 | 28 | public static boolean isEmpty(Collection collection) { 29 | return collection == null || collection.isEmpty(); 30 | } 31 | 32 | public static boolean isEmpty(Map map) { 33 | return map == null || map.isEmpty(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/util/IgnoreSSLUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.util; 17 | 18 | import org.apache.http.config.Registry; 19 | import org.apache.http.config.RegistryBuilder; 20 | import org.apache.http.conn.socket.ConnectionSocketFactory; 21 | import org.apache.http.conn.socket.PlainConnectionSocketFactory; 22 | import org.apache.http.conn.ssl.SSLConnectionSocketFactory; 23 | import org.apache.http.impl.client.CloseableHttpClient; 24 | import org.apache.http.impl.client.HttpClients; 25 | import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; 26 | 27 | import javax.net.ssl.SSLContext; 28 | import javax.net.ssl.TrustManager; 29 | import javax.net.ssl.X509TrustManager; 30 | import java.security.KeyManagementException; 31 | import java.security.NoSuchAlgorithmException; 32 | import java.security.cert.CertificateException; 33 | 34 | /** 35 | * A tool for ignoring ssl when creating httpclient 36 | */ 37 | public class IgnoreSSLUtils { 38 | private static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException { 39 | SSLContext sc = SSLContext.getInstance("TLSv1.2"); 40 | 41 | X509TrustManager trustManager = new X509TrustManager() { 42 | @Override 43 | public void checkClientTrusted( 44 | java.security.cert.X509Certificate[] paramArrayOfX509Certificate, 45 | String paramString) throws CertificateException { 46 | } 47 | 48 | @Override 49 | public void checkServerTrusted( 50 | java.security.cert.X509Certificate[] paramArrayOfX509Certificate, 51 | String paramString) throws CertificateException { 52 | } 53 | 54 | @Override 55 | public java.security.cert.X509Certificate[] getAcceptedIssuers() { 56 | return null; 57 | } 58 | }; 59 | 60 | sc.init(null, new TrustManager[]{trustManager}, null); 61 | return sc; 62 | } 63 | 64 | /** 65 | * for ignoring verify SSL 66 | */ 67 | public static CloseableHttpClient createClient() throws KeyManagementException, NoSuchAlgorithmException { 68 | SSLContext sslcontext = createIgnoreVerifySSL(); 69 | 70 | Registry socketFactoryRegistry = RegistryBuilder.create() 71 | .register("http", PlainConnectionSocketFactory.INSTANCE) 72 | .register("https", new SSLConnectionSocketFactory(sslcontext)) 73 | .build(); 74 | PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); 75 | HttpClients.custom().setConnectionManager(connManager); 76 | 77 | return HttpClients.custom().setConnectionManager(connManager).build(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/util/InitAppUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Huawei Technologies Co., Ltd. 2019-2024. All rights reserved. 3 | */ 4 | package com.huawei.push.util; 5 | 6 | import com.huawei.push.messaging.HuaweiApp; 7 | import com.huawei.push.messaging.HuaweiCredential; 8 | import com.huawei.push.messaging.HuaweiOption; 9 | 10 | import java.util.ResourceBundle; 11 | 12 | public class InitAppUtils { 13 | /** 14 | * @return HuaweiApp 15 | */ 16 | public static HuaweiApp initializeApp() { 17 | String appId = ResourceBundle.getBundle("url").getString("appid"); 18 | String appSecret = ResourceBundle.getBundle("url").getString("appsecret"); 19 | // Create HuaweiCredential 20 | // This appId and appSecret come from Huawei Developer Alliance 21 | return initializeApp(appId, appSecret); 22 | } 23 | 24 | private static HuaweiApp initializeApp(String appId, String appSecret) { 25 | HuaweiCredential credential = HuaweiCredential.builder() 26 | .setAppId(appId) 27 | .setAppSecret(appSecret) 28 | .build(); 29 | 30 | // Create HuaweiOption 31 | HuaweiOption option = HuaweiOption.builder() 32 | .setCredential(credential) 33 | .build(); 34 | 35 | // Initialize HuaweiApp 36 | // return HuaweiApp.initializeApp(option); 37 | return HuaweiApp.getInstance(option); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/util/ResponceCodeProcesser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.util; 17 | 18 | import java.util.HashMap; 19 | import java.util.Map; 20 | 21 | /** 22 | * A tool for processing the responce code 23 | */ 24 | public class ResponceCodeProcesser { 25 | private static final Map codeMap = new HashMap() { 26 | { 27 | put(80000000, "Success"); 28 | put(80100000, "Some tokens are right, the others are illegal"); 29 | put(80100001, "Parameters check error"); 30 | put(80100002, "Token number should be one when send sys message"); 31 | put(80100003, "Message structure error"); 32 | put(80100004, "TTL is less than current time, please check"); 33 | put(80100013, "Collapse_key is illegal, please check"); 34 | put(80100016, "Message contians sensitive information, please check"); 35 | put(80100017, "A maximum of 100 topic-based messages can be sent at the same time."); 36 | put(80100018, "Invalid message body"); 37 | put(80200001, "Oauth authentication error"); 38 | put(80200003, "Oauth Token expired"); 39 | put(80300002, "APP is forbidden to send"); 40 | put(80300007, "Invalid Token"); 41 | put(80300008, "The message body size exceeds the default value set by the system (4K)"); 42 | put(80300010, "Tokens exceed the default value"); 43 | put(80300011, "No permission to send high-level notification messages"); 44 | put(80600003, "Request OAuth service failed"); 45 | put(81000001, "System inner error"); 46 | put(82000001, "GroupKey or groupName error"); 47 | put(82000002, "GroupKey and groupName do not match"); 48 | put(82000003, "Token array is null"); 49 | put(82000004, "Group do not exist"); 50 | put(82000005, "Group do not belond to this app"); 51 | put(82000006, "Token array or group number is transfinited"); 52 | put(82000007, "Invalid topic"); 53 | put(82000008, "Token array null or transfinited"); 54 | put(82000009, "Topic num transfinited, at most 2000"); 55 | put(82000010, "Some token is wrong"); 56 | put(82000011, "Token is null"); 57 | put(82000012, "Data storage location is not selected"); 58 | put(82000013, "Data storage location does not match the actual data"); 59 | } 60 | }; 61 | 62 | public static String process(Integer code) { 63 | return codeMap.getOrDefault(code, "Unknown code"); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/util/ValidatorUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.util; 17 | 18 | /** 19 | * A tool for validating the parameters 20 | */ 21 | public class ValidatorUtils { 22 | 23 | public static void checkArgument(boolean expression) { 24 | if (!expression) { 25 | throw new IllegalArgumentException(); 26 | } 27 | } 28 | 29 | public static void checkArgument(boolean expression, Object errorMessage) { 30 | if (!expression) { 31 | throw new IllegalArgumentException(String.valueOf(errorMessage)); 32 | } 33 | } 34 | 35 | public static void checkState(boolean expression, Object errorMessage) { 36 | if (!expression) { 37 | throw new IllegalStateException(String.valueOf(errorMessage)); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/webpush/WebActions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.webpush; 17 | 18 | import com.alibaba.fastjson.annotation.JSONField; 19 | 20 | public class WebActions { 21 | @JSONField(name = "action") 22 | private String action; 23 | 24 | @JSONField(name = "icon") 25 | private String icon; 26 | 27 | @JSONField(name = "title") 28 | private String title; 29 | 30 | public String getAction() { 31 | return action; 32 | } 33 | 34 | public String getIcon() { 35 | return icon; 36 | } 37 | 38 | public String getTitle() { 39 | return title; 40 | } 41 | 42 | public void check(){ 43 | 44 | } 45 | 46 | public WebActions(Builder builder) { 47 | this.action = builder.action; 48 | this.icon = builder.icon; 49 | this.title = builder.title; 50 | } 51 | 52 | /** 53 | * builder 54 | */ 55 | public static Builder builder() { 56 | return new Builder(); 57 | } 58 | 59 | public static class Builder { 60 | private String action; 61 | private String icon; 62 | private String title; 63 | 64 | public Builder setAction(String action) { 65 | this.action = action; 66 | return this; 67 | } 68 | 69 | public Builder setIcon(String icon) { 70 | this.icon = icon; 71 | return this; 72 | } 73 | 74 | public Builder setTitle(String title) { 75 | this.title = title; 76 | return this; 77 | } 78 | 79 | public WebActions build() { 80 | return new WebActions(this); 81 | } 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/webpush/WebHmsOptions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.webpush; 17 | 18 | import com.alibaba.fastjson.annotation.JSONField; 19 | import com.huawei.push.util.ValidatorUtils; 20 | 21 | import org.apache.commons.lang3.StringUtils; 22 | 23 | import java.net.MalformedURLException; 24 | import java.net.URL; 25 | 26 | public class WebHmsOptions { 27 | @JSONField(name = "link") 28 | private String link; 29 | 30 | public String getLink() { 31 | return link; 32 | } 33 | 34 | public WebHmsOptions(Builder builder) { 35 | this.link = builder.link; 36 | } 37 | 38 | public void check() { 39 | if (!StringUtils.isEmpty(this.link)) { 40 | try { 41 | new URL(link); 42 | } catch (MalformedURLException e) { 43 | ValidatorUtils.checkArgument(false, "Invalid link"); 44 | } 45 | } 46 | } 47 | 48 | /** 49 | * builder 50 | */ 51 | public static Builder builder() { 52 | return new Builder(); 53 | } 54 | 55 | public static class Builder { 56 | private String link; 57 | 58 | public Builder setLink(String link) { 59 | this.link = link; 60 | return this; 61 | } 62 | 63 | public WebHmsOptions build() { 64 | return new WebHmsOptions(this); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/webpush/WebNotification.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.webpush; 17 | 18 | import com.alibaba.fastjson.annotation.JSONField; 19 | import com.huawei.push.util.CollectionUtils; 20 | import com.huawei.push.util.ValidatorUtils; 21 | 22 | import java.util.ArrayList; 23 | import java.util.Arrays; 24 | import java.util.List; 25 | 26 | public class WebNotification { 27 | private static String[] DIR_VALUE = {"auto", "ltr", "rtl"}; 28 | 29 | @JSONField(name = "title") 30 | private String title; 31 | 32 | @JSONField(name = "body") 33 | private String body; 34 | 35 | @JSONField(name = "icon") 36 | private String icon; 37 | 38 | @JSONField(name = "image") 39 | private String image; 40 | 41 | @JSONField(name = "lang") 42 | private String lang; 43 | 44 | @JSONField(name = "tag") 45 | private String tag; 46 | 47 | @JSONField(name = "badge") 48 | private String badge; 49 | 50 | @JSONField(name = "dir") 51 | private String dir; 52 | 53 | @JSONField(name = "vibrate") 54 | private List vibrate = new ArrayList<>(); 55 | 56 | @JSONField(name = "renotify") 57 | private boolean renotify; 58 | 59 | @JSONField(name = "require_interaction") 60 | private boolean requireInteraction; 61 | 62 | @JSONField(name = "silent") 63 | private boolean silent; 64 | 65 | @JSONField(name = "timestamp") 66 | private Long timestamp; 67 | 68 | @JSONField(name = "actions") 69 | private List actions = new ArrayList(); 70 | 71 | public String getTitle() { 72 | return title; 73 | } 74 | 75 | public String getBody() { 76 | return body; 77 | } 78 | 79 | public String getIcon() { 80 | return icon; 81 | } 82 | 83 | public String getImage() { 84 | return image; 85 | } 86 | 87 | public String getLang() { 88 | return lang; 89 | } 90 | 91 | public String getTag() { 92 | return tag; 93 | } 94 | 95 | public String getBadge() { 96 | return badge; 97 | } 98 | 99 | public String getDir() { 100 | return dir; 101 | } 102 | 103 | public List getVibrate() { 104 | return vibrate; 105 | } 106 | 107 | public boolean isRenotify() { 108 | return renotify; 109 | } 110 | 111 | public boolean isRequireInteraction() { 112 | return requireInteraction; 113 | } 114 | 115 | public boolean isSilent() { 116 | return silent; 117 | } 118 | 119 | public Long getTimestamp() { 120 | return timestamp; 121 | } 122 | 123 | public List getActions() { 124 | return actions; 125 | } 126 | 127 | public void check() { 128 | if (this.dir != null) { 129 | ValidatorUtils.checkArgument(Arrays.stream(DIR_VALUE).anyMatch(value -> value.equals(dir)), "Invalid dir"); 130 | } 131 | if (this.vibrate != null) { 132 | for (Object obj : vibrate) { 133 | ValidatorUtils.checkArgument((obj instanceof Double || obj instanceof Integer), "Invalid vibrate"); 134 | } 135 | } 136 | } 137 | 138 | public WebNotification(Builder builder) { 139 | this.title = builder.title; 140 | this.body = builder.body; 141 | this.icon = builder.icon; 142 | this.image = builder.image; 143 | this.lang = builder.lang; 144 | this.tag = builder.tag; 145 | this.badge = builder.badge; 146 | this.dir = builder.dir; 147 | if (!CollectionUtils.isEmpty(builder.vibrate)) { 148 | this.vibrate.addAll(builder.vibrate); 149 | } else { 150 | this.vibrate = null; 151 | } 152 | 153 | this.renotify = builder.renotify; 154 | this.requireInteraction = builder.requireInteraction; 155 | this.silent = builder.silent; 156 | this.timestamp = builder.timestamp; 157 | if (!CollectionUtils.isEmpty(builder.actions)) { 158 | this.actions.addAll(builder.actions); 159 | } else { 160 | this.actions = null; 161 | } 162 | } 163 | 164 | /** 165 | * builder 166 | */ 167 | public static Builder builder() { 168 | return new Builder(); 169 | } 170 | 171 | public static class Builder { 172 | private String title; 173 | private String body; 174 | private String icon; 175 | private String image; 176 | private String lang; 177 | private String tag; 178 | private String badge; 179 | private String dir; 180 | private List vibrate = new ArrayList<>(); 181 | private boolean renotify; 182 | private boolean requireInteraction; 183 | private boolean silent; 184 | private Long timestamp; 185 | private List actions = new ArrayList(); 186 | 187 | public Builder setTitle(String title) { 188 | this.title = title; 189 | return this; 190 | } 191 | 192 | public Builder setBody(String body) { 193 | this.body = body; 194 | return this; 195 | } 196 | 197 | public Builder setIcon(String icon) { 198 | this.icon = icon; 199 | return this; 200 | } 201 | 202 | public Builder setImage(String image) { 203 | this.image = image; 204 | return this; 205 | } 206 | 207 | public Builder setLang(String lang) { 208 | this.lang = lang; 209 | return this; 210 | } 211 | 212 | public Builder setTag(String tag) { 213 | this.tag = tag; 214 | return this; 215 | } 216 | 217 | public Builder setBadge(String badge) { 218 | this.badge = badge; 219 | return this; 220 | } 221 | 222 | public Builder setDir(String dir) { 223 | this.dir = dir; 224 | return this; 225 | } 226 | 227 | public Builder addAllVibrate(List vibrate) { 228 | this.vibrate.addAll(vibrate); 229 | return this; 230 | } 231 | 232 | public Builder addVibrate(Integer vibrate) { 233 | this.vibrate.add(vibrate); 234 | return this; 235 | } 236 | 237 | public Builder setRenotify(boolean renotify) { 238 | this.renotify = renotify; 239 | return this; 240 | } 241 | 242 | public Builder setRequireInteraction(boolean requireInteraction) { 243 | this.requireInteraction = requireInteraction; 244 | return this; 245 | } 246 | 247 | public Builder setSilent(boolean silent) { 248 | this.silent = silent; 249 | return this; 250 | } 251 | 252 | public Builder setTimestamp(Long timestamp) { 253 | this.timestamp = timestamp; 254 | return this; 255 | } 256 | 257 | public Builder addAllActions(List actions) { 258 | this.actions.addAll(actions); 259 | return this; 260 | } 261 | 262 | public Builder addAction(WebActions action) { 263 | this.actions.add(action); 264 | return this; 265 | } 266 | 267 | public WebNotification build() { 268 | return new WebNotification(this); 269 | } 270 | 271 | } 272 | 273 | } 274 | -------------------------------------------------------------------------------- /src/main/java/com/huawei/push/webpush/WebpushHeaders.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. Huawei Technologies Co., Ltd. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.huawei.push.webpush; 17 | 18 | import com.alibaba.fastjson.annotation.JSONField; 19 | import com.huawei.push.util.ValidatorUtils; 20 | 21 | import java.util.Arrays; 22 | 23 | public class WebpushHeaders { 24 | private static String TTL_PATTERN = "[0-9]+|[0-9]+[sS]"; 25 | 26 | private static String[] URGENCY_VALUE = {"very-low", "low", "normal", "high"}; 27 | 28 | @JSONField(name = "ttl") 29 | private String ttl; 30 | 31 | @JSONField(name = "topic") 32 | private String topic; 33 | 34 | @JSONField(name = "urgency") 35 | private String urgency; 36 | 37 | public String getTtl() { 38 | return ttl; 39 | } 40 | 41 | public String getTopic() { 42 | return topic; 43 | } 44 | 45 | public String getUrgency() { 46 | return urgency; 47 | } 48 | 49 | public WebpushHeaders(Builder builder) { 50 | this.ttl = builder.ttl; 51 | this.topic = builder.topic; 52 | this.urgency = builder.urgency; 53 | } 54 | 55 | public void check() { 56 | if (this.ttl != null) { 57 | ValidatorUtils.checkArgument(this.ttl.matches(TTL_PATTERN), "Invalid ttl format"); 58 | } 59 | if (this.urgency != null) { 60 | ValidatorUtils.checkArgument(Arrays.stream(URGENCY_VALUE).anyMatch(value -> value.equals(urgency)),"Invalid urgency"); 61 | } 62 | } 63 | 64 | /** 65 | * builder 66 | */ 67 | public static Builder builder() { 68 | return new Builder(); 69 | } 70 | 71 | public static class Builder { 72 | private String ttl; 73 | private String topic; 74 | private String urgency; 75 | 76 | public Builder setTtl(String ttl) { 77 | this.ttl = ttl; 78 | return this; 79 | } 80 | 81 | public Builder setTopic(String topic) { 82 | this.topic = topic; 83 | return this; 84 | } 85 | 86 | public Builder setUrgency(String urgency) { 87 | this.urgency = urgency; 88 | return this; 89 | } 90 | 91 | public WebpushHeaders build() { 92 | return new WebpushHeaders(this); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/resources/url.properties: -------------------------------------------------------------------------------- 1 | appid = your app id 2 | appsecret = your app secret 3 | token_server = https://oauth-login.cloud.huawei.com/oauth2/v3/token 4 | push_open_url = https://push-api.cloud.huawei.com 5 | -------------------------------------------------------------------------------- /test/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | target 3 | 4 | 5 | --------------------------------------------------------------------------------