Skip to content

Commit f83cdec

Browse files
authored
Firebase Cloud Messaging API (#127)
* Adding experimental FCM API * Added Webpush notification support * Added APNS support and tests * Added subscribe method * Added TopicManagementResponse type * Added unsub method * Improved error handling and json parsing * More tests, validation and dry run mode * Improved error handling and tests * Added license header; Implemented topic name normalization * Improved error handling * Improved error handling * Added javadocs * Fixing auth (ADC) test failure * Updated documentation * Updated documentation * Updated javadocs * Updated test * Renamed Priority enum values (using uppercase) * Adding APNS types * Updated APNS documentation * Updated integration test * Making TTL a long argument * Updated changelog * Addressing a number of readability nits, and other code review comments * Fixing some nits * Removing some duplicate code in messaging tests * Further deduping code in test * Accept prefixed topic names (#136) * Accept prefixed topic names * Parsing topic name in a helper method * Updated javadoc for setTopic() * Updated FCM error codes (#138) * Merged with dev; updated changelog * Updated changelog
1 parent 2b599c0 commit f83cdec

17 files changed

+3176
-42
lines changed

CHANGELOG.md

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,39 @@
11
# Unreleased
22

3-
### Token revocation
4-
- [added] The [`verifyIdTokenAsync(...)`](https://firebase.google.com/docs/reference/admin/java/reference/com/google/firebase/auth/FirebaseAuth.html#verifyIdTokenAsync)
5-
method has an added signature that accepts a boolean `checkRevoked` parameter. When `true`, an
6-
additional check is performed to see whether the token has been revoked.
7-
- [added] A new method [`FirebaseAuth.revokeRefreshTokensAsync(uid)`](https://firebase.google.com/docs/reference/admin/java/reference/com/google/firebase/auth/FirebaseAuth.html#revokeRefreshTokens)
8-
has been added to invalidate all tokens issued to a user before the current second.
9-
- [added] A new getter `getTokensValidAfterTimestamp()` has been added to the
10-
[`UserRecord`](https://firebase.google.com/docs/reference/admin/java/reference/com/google/firebase/auth/UserRecord),
11-
which denotes the time in epoch milliseconds before which tokens are not valid. This is truncated to 1000 milliseconds.
3+
### Cloud Messaging
4+
5+
- [feature] Added the `FirebaseCloudMessaging` API for sending
6+
Firebase notifications and managing topic subscriptions.
7+
8+
### Authentication
9+
10+
- [added] The [`verifyIdTokenAsync()`](https://firebase.google.com/docs/reference/admin/java/reference/com/google/firebase/auth/FirebaseAuth.html#verifyIdTokenAsync)
11+
method has an overload that accepts a boolean `checkRevoked` parameter.
12+
When `true`, an additional check is performed to see whether the token
13+
has been revoked.
14+
- [added] A new [`revokeRefreshTokensAsync()`](https://firebase.google.com/docs/reference/admin/java/reference/com/google/firebase/auth/FirebaseAuth.html#revokeRefreshTokens)
15+
method has been added to invalidate all tokens issued to a user.
16+
- [added] A new getter `getTokensValidAfterTimestamp()` has been added
17+
to the [`UserRecord`](https://firebase.google.com/docs/reference/admin/java/reference/com/google/firebase/auth/UserRecord)
18+
class, which denotes the time before which tokens are not valid.
19+
20+
### Realtime Database
21+
22+
- [fixed] Exceptions thrown by database event handlers are now logged.
1223

1324
### Initialization
1425

1526
- [fixed] The [`FirebaseOptions.Builder.setStorageBucket()`](https://firebase.google.com/docs/reference/admin/java/reference/com/google/firebase/FirebaseOptions.Builder.html#setStorageBucket(java.lang.String))
1627
method now throws a clear exception when invoked with a bucket URL
1728
instead of the name.
29+
- [fixed] Implemented a fix for a potential Guava version conflict which
30+
was causing an `IllegalStateException` (precondition failure) in some
31+
environments.
1832

19-
### Realtime Database
33+
### Cloud Firestore
2034

21-
- [fixed] Exceptions thrown by database event handlers are now logged.
35+
- [fixed] Upgraded the Cloud Firestore client to the latest available
36+
version.
2237

2338
# v5.8.0
2439

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
/*
2+
* Copyright 2018 Google Inc.
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+
17+
package com.google.firebase.messaging;
18+
19+
import static com.google.common.base.Preconditions.checkArgument;
20+
21+
import com.google.api.client.util.Key;
22+
import com.google.common.collect.ImmutableMap;
23+
import com.google.firebase.internal.NonNull;
24+
import java.util.HashMap;
25+
import java.util.Map;
26+
import java.util.concurrent.TimeUnit;
27+
28+
/**
29+
* Represents the Android-specific options that can be included in a {@link Message}.
30+
* Instances of this class are thread-safe and immutable.
31+
*/
32+
public class AndroidConfig {
33+
34+
@Key("collapse_key")
35+
private final String collapseKey;
36+
37+
@Key("priority")
38+
private final String priority;
39+
40+
@Key("ttl")
41+
private final String ttl;
42+
43+
@Key("restricted_package_name")
44+
private final String restrictedPackageName;
45+
46+
@Key("data")
47+
private final Map<String, String> data;
48+
49+
@Key("notification")
50+
private final AndroidNotification notification;
51+
52+
private AndroidConfig(Builder builder) {
53+
this.collapseKey = builder.collapseKey;
54+
if (builder.priority != null) {
55+
this.priority = builder.priority.name().toLowerCase();
56+
} else {
57+
this.priority = null;
58+
}
59+
if (builder.ttl != null) {
60+
checkArgument(builder.ttl >= 0, "ttl must not be negative");
61+
long seconds = TimeUnit.MILLISECONDS.toSeconds(builder.ttl);
62+
long subsecondNanos = TimeUnit.MILLISECONDS.toNanos(builder.ttl - seconds * 1000L);
63+
if (subsecondNanos > 0) {
64+
this.ttl = String.format("%d.%09ds", seconds, subsecondNanos);
65+
} else {
66+
this.ttl = String.format("%ds", seconds);
67+
}
68+
} else {
69+
this.ttl = null;
70+
}
71+
this.restrictedPackageName = builder.restrictedPackageName;
72+
this.data = builder.data.isEmpty() ? null : ImmutableMap.copyOf(builder.data);
73+
this.notification = builder.notification;
74+
}
75+
76+
/**
77+
* Priority levels that can be set on an {@link AndroidConfig}.
78+
*/
79+
public enum Priority {
80+
HIGH,
81+
NORMAL,
82+
}
83+
84+
/**
85+
* Creates a new {@link AndroidConfig.Builder}.
86+
*
87+
* @return A {@link AndroidConfig.Builder} instance.
88+
*/
89+
public static Builder builder() {
90+
return new Builder();
91+
}
92+
93+
public static class Builder {
94+
95+
private String collapseKey;
96+
private Priority priority;
97+
private Long ttl;
98+
private String restrictedPackageName;
99+
private final Map<String, String> data = new HashMap<>();
100+
private AndroidNotification notification;
101+
102+
private Builder() {}
103+
104+
/**
105+
* Sets a collapse key for the message. Collapse key serves as an identifier for a group of
106+
* messages that can be collapsed, so that only the last message gets sent when delivery can be
107+
* resumed. A maximum of 4 different collapse keys may be active at any given time.
108+
*
109+
* @param collapseKey A collapse key string.
110+
* @return This builder.
111+
*/
112+
public Builder setCollapseKey(String collapseKey) {
113+
this.collapseKey = collapseKey;
114+
return this;
115+
}
116+
117+
/**
118+
* Sets the priority of the message.
119+
*
120+
* @param priority A value from the {@link Priority} enum.
121+
* @return This builder.
122+
*/
123+
public Builder setPriority(Priority priority) {
124+
this.priority = priority;
125+
return this;
126+
}
127+
128+
/**
129+
* Sets the time-to-live duration of the message in milliseconds.
130+
*
131+
* @param ttl Time-to-live duration in milliseconds.
132+
* @return This builder.
133+
*/
134+
public Builder setTtl(long ttl) {
135+
this.ttl = ttl;
136+
return this;
137+
}
138+
139+
/**
140+
* Sets the package name of the application where the registration tokens must match in order
141+
* to receive the message.
142+
*
143+
* @param restrictedPackageName A package name string.
144+
* @return This builder.
145+
*/
146+
public Builder setRestrictedPackageName(String restrictedPackageName) {
147+
this.restrictedPackageName = restrictedPackageName;
148+
return this;
149+
}
150+
151+
/**
152+
* Adds the given key-value pair to the message as a data field. Key and the value may not be
153+
* null. When set, overrides any data fields set on the top-level {@link Message} via
154+
* {@link Message.Builder#putData(String, String)} and {@link Message.Builder#putAllData(Map)}.
155+
*
156+
* @param key Name of the data field. Must not be null.
157+
* @param value Value of the data field. Must not be null.
158+
* @return This builder.
159+
*/
160+
public Builder putData(@NonNull String key, @NonNull String value) {
161+
this.data.put(key, value);
162+
return this;
163+
}
164+
165+
/**
166+
* Adds all the key-value pairs in the given map to the message as data fields. None of the
167+
* keys and values may be null. When set, overrides any data fields set on the top-level
168+
* {@link Message} via {@link Message.Builder#putData(String, String)} and
169+
* {@link Message.Builder#putAllData(Map)}.
170+
*
171+
* @param map A non-null map of data fields. Map must not contain null keys or values.
172+
* @return This builder.
173+
*/
174+
public Builder putAllData(@NonNull Map<String, String> map) {
175+
this.data.putAll(map);
176+
return this;
177+
}
178+
179+
/**
180+
* Sets the Android notification to be included in the message.
181+
*
182+
* @param notification An {@link AndroidNotification} instance.
183+
* @return This builder.
184+
*/
185+
public Builder setNotification(AndroidNotification notification) {
186+
this.notification = notification;
187+
return this;
188+
}
189+
190+
/**
191+
* Creates a new {@link AndroidConfig} instance from the parameters set on this builder.
192+
*
193+
* @return A new {@link AndroidConfig} instance.
194+
* @throws IllegalArgumentException If any of the parameters set on the builder are invalid.
195+
*/
196+
public AndroidConfig build() {
197+
return new AndroidConfig(this);
198+
}
199+
}
200+
}

0 commit comments

Comments
 (0)