Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
7249ab7
Adding experimental FCM API
hiranya911 Dec 25, 2017
12f7da8
Added Webpush notification support
hiranya911 Dec 28, 2017
f095734
Added APNS support and tests
hiranya911 Dec 28, 2017
c037733
Added subscribe method
hiranya911 Dec 28, 2017
da0f5d1
Added TopicManagementResponse type
hiranya911 Dec 28, 2017
565fd01
Added unsub method
hiranya911 Dec 28, 2017
174b302
Improved error handling and json parsing
hiranya911 Dec 29, 2017
97a15a0
More tests, validation and dry run mode
hiranya911 Jan 2, 2018
4798b43
Improved error handling and tests
hiranya911 Jan 3, 2018
4aecab9
Added license header; Implemented topic name normalization
hiranya911 Jan 3, 2018
5a22fcb
Improved error handling
hiranya911 Jan 3, 2018
b856625
Improved error handling
hiranya911 Jan 3, 2018
84f9908
Added javadocs
hiranya911 Jan 17, 2018
e845957
Merge branch 'master' into hkj-fcm-api
hiranya911 Jan 17, 2018
13ae556
Fixing auth (ADC) test failure
hiranya911 Jan 17, 2018
c2d8462
Updated documentation
hiranya911 Jan 17, 2018
a4661a0
Updated documentation
hiranya911 Jan 17, 2018
084e8e9
Updated javadocs
hiranya911 Jan 18, 2018
f898ad1
Updated test
hiranya911 Jan 18, 2018
9e5e7e7
Renamed Priority enum values (using uppercase)
hiranya911 Jan 18, 2018
1b598a4
Adding APNS types
hiranya911 Jan 19, 2018
c2b3d55
Merge branch 'hkj-fcm-api' of github.com:firebase/firebase-admin-java…
hiranya911 Jan 19, 2018
f971206
Updated APNS documentation
hiranya911 Jan 19, 2018
7a2b311
Updated integration test
hiranya911 Jan 19, 2018
7859c86
Merge branch 'master' into hkj-fcm-api
hiranya911 Jan 26, 2018
ac5625d
Making TTL a long argument
hiranya911 Jan 26, 2018
83d2ac4
Updated changelog
hiranya911 Jan 26, 2018
24d38ad
Merged with master
hiranya911 Jan 29, 2018
c6043be
Addressing a number of readability nits, and other code review comments
hiranya911 Jan 30, 2018
011e6e8
Fixing some nits
hiranya911 Feb 1, 2018
668b29f
Removing some duplicate code in messaging tests
hiranya911 Feb 6, 2018
854c6df
Further deduping code in test
hiranya911 Feb 7, 2018
b96b220
Accept prefixed topic names (#136)
hiranya911 Feb 7, 2018
5531a08
Updated FCM error codes (#138)
hiranya911 Feb 12, 2018
0b4bf41
Merge branch 'master' into hkj-fcm-api
hiranya911 Feb 13, 2018
a2a1447
Merge branch 'master' into hkj-fcm-api
hiranya911 Feb 13, 2018
7fc9fe0
Merged with dev; updated changelog
hiranya911 Feb 13, 2018
374a643
Updated changelog
hiranya911 Feb 13, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 26 additions & 11 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,39 @@
# Unreleased

### Token revocation
- [added] The [`verifyIdTokenAsync(...)`](https://firebase.google.com/docs/reference/admin/java/reference/com/google/firebase/auth/FirebaseAuth.html#verifyIdTokenAsync)
method has an added signature that accepts a boolean `checkRevoked` parameter. When `true`, an
additional check is performed to see whether the token has been revoked.
- [added] A new method [`FirebaseAuth.revokeRefreshTokensAsync(uid)`](https://firebase.google.com/docs/reference/admin/java/reference/com/google/firebase/auth/FirebaseAuth.html#revokeRefreshTokens)
has been added to invalidate all tokens issued to a user before the current second.
- [added] A new getter `getTokensValidAfterTimestamp()` has been added to the
[`UserRecord`](https://firebase.google.com/docs/reference/admin/java/reference/com/google/firebase/auth/UserRecord),
which denotes the time in epoch milliseconds before which tokens are not valid. This is truncated to 1000 milliseconds.
### Cloud Messaging

- [feature] Added the `FirebaseCloudMessaging` API for sending
Firebase notifications and managing topic subscriptions.

### Authentication

- [added] The [`verifyIdTokenAsync()`](https://firebase.google.com/docs/reference/admin/java/reference/com/google/firebase/auth/FirebaseAuth.html#verifyIdTokenAsync)
method has an overload that accepts a boolean `checkRevoked` parameter.
When `true`, an additional check is performed to see whether the token
has been revoked.
- [added] A new [`revokeRefreshTokensAsync()`](https://firebase.google.com/docs/reference/admin/java/reference/com/google/firebase/auth/FirebaseAuth.html#revokeRefreshTokens)
method has been added to invalidate all tokens issued to a user.
- [added] A new getter `getTokensValidAfterTimestamp()` has been added
to the [`UserRecord`](https://firebase.google.com/docs/reference/admin/java/reference/com/google/firebase/auth/UserRecord)
class, which denotes the time before which tokens are not valid.

### Realtime Database

- [fixed] Exceptions thrown by database event handlers are now logged.

### Initialization

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

### Realtime Database
### Cloud Firestore

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

# v5.8.0

Expand Down
200 changes: 200 additions & 0 deletions src/main/java/com/google/firebase/messaging/AndroidConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
/*
* Copyright 2018 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.firebase.messaging;

import static com.google.common.base.Preconditions.checkArgument;

import com.google.api.client.util.Key;
import com.google.common.collect.ImmutableMap;
import com.google.firebase.internal.NonNull;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
* Represents the Android-specific options that can be included in a {@link Message}.
* Instances of this class are thread-safe and immutable.
Copy link
Contributor

@schmidt-sebastian schmidt-sebastian Jan 30, 2018

Choose a reason for hiding this comment

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

How does this show up in the JavaDoc output? I wonder if we should add a newline (or <p>).

Copy link
Contributor Author

@hiranya911 hiranya911 Jan 30, 2018

Choose a reason for hiding this comment

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

They show up as a single paragraph. We already have a quite a bit of similarly documented classes (See UserRecord class from auth for example)

*/
public class AndroidConfig {

@Key("collapse_key")
private final String collapseKey;

@Key("priority")
private final String priority;

@Key("ttl")
private final String ttl;

@Key("restricted_package_name")
private final String restrictedPackageName;

@Key("data")
private final Map<String, String> data;

@Key("notification")
private final AndroidNotification notification;

private AndroidConfig(Builder builder) {
this.collapseKey = builder.collapseKey;
if (builder.priority != null) {
this.priority = builder.priority.name().toLowerCase();
} else {
this.priority = null;
}
if (builder.ttl != null) {
checkArgument(builder.ttl >= 0, "ttl must not be negative");
long seconds = TimeUnit.MILLISECONDS.toSeconds(builder.ttl);
long subsecondNanos = TimeUnit.MILLISECONDS.toNanos(builder.ttl - seconds * 1000L);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this should be 1000 * 1000.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

builder.ttl is in millis. So I believe this is correct. We have a test case for this where 10ms is correctly transformed to 0.010000000s (where the decimal part is subsecond nanos).

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry, I think I had nanoseconds in my head.

if (subsecondNanos > 0) {
this.ttl = String.format("%d.%09ds", seconds, subsecondNanos);
} else {
this.ttl = String.format("%ds", seconds);
}
} else {
this.ttl = null;
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: This is not needed since it is the default (here and above)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is needed since it's final

}
this.restrictedPackageName = builder.restrictedPackageName;
this.data = builder.data.isEmpty() ? null : ImmutableMap.copyOf(builder.data);
this.notification = builder.notification;
}

/**
* Priority levels that can be set on an {@link AndroidConfig}.
*/
public enum Priority {
HIGH,
NORMAL,
}

/**
* Creates a new {@link AndroidConfig.Builder}.
*
* @return A {@link AndroidConfig.Builder} instance.
*/
public static Builder builder() {
return new Builder();
}

public static class Builder {

private String collapseKey;
private Priority priority;
private Long ttl;
private String restrictedPackageName;
private final Map<String, String> data = new HashMap<>();
private AndroidNotification notification;

private Builder() {}

/**
* Sets a collapse key for the message. Collapse key serves as an identifier for a group of
* messages that can be collapsed, so that only the last message gets sent when delivery can be
* resumed. A maximum of 4 different collapse keys may be active at any given time.
*
* @param collapseKey A collapse key string.
* @return This builder.
*/
public Builder setCollapseKey(String collapseKey) {
this.collapseKey = collapseKey;
return this;
}

/**
* Sets the priority of the message.
*
* @param priority A value from the {@link Priority} enum.
* @return This builder.
*/
public Builder setPriority(Priority priority) {
this.priority = priority;
return this;
}

/**
* Sets the time-to-live duration of the message in milliseconds.
*
* @param ttl Time-to-live duration in milliseconds.
* @return This builder.
*/
public Builder setTtl(long ttl) {
this.ttl = ttl;
return this;
}

/**
* Sets the package name of the application where the registration tokens must match in order
* to receive the message.
*
* @param restrictedPackageName A package name string.
* @return This builder.
*/
public Builder setRestrictedPackageName(String restrictedPackageName) {
this.restrictedPackageName = restrictedPackageName;
return this;
}

/**
* Adds the given key-value pair to the message as a data field. Key and the value may not be
* null. When set, overrides any data fields set on the top-level {@link Message} via
* {@link Message.Builder#putData(String, String)} and {@link Message.Builder#putAllData(Map)}.
*
* @param key Name of the data field. Must not be null.
* @param value Value of the data field. Must not be null.
* @return This builder.
*/
public Builder putData(@NonNull String key, @NonNull String value) {
this.data.put(key, value);
Copy link
Contributor

@schmidt-sebastian schmidt-sebastian Jan 30, 2018

Choose a reason for hiding this comment

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

This doesn't override the existing value. Do you instead mean that the final AndroidConfig's data map will be overridden?

Copy link
Contributor Author

@hiranya911 hiranya911 Jan 30, 2018

Choose a reason for hiding this comment

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

It overrides the data set using the Message.Builder class. It's an FCM mechanic executed at the backend. In other words AndroidConfig.data map gets priority over Message.data map when FCM sends notifications. I've slightly modified the text to make this clear.

return this;
}

/**
* Adds all the key-value pairs in the given map to the message as data fields. None of the
* keys and values may be null. When set, overrides any data fields set on the top-level
* {@link Message} via {@link Message.Builder#putData(String, String)} and
* {@link Message.Builder#putAllData(Map)}.
*
* @param map A non-null map of data fields. Map must not contain null keys or values.
* @return This builder.
*/
public Builder putAllData(@NonNull Map<String, String> map) {
this.data.putAll(map);
return this;
}

/**
* Sets the Android notification to be included in the message.
*
* @param notification An {@link AndroidNotification} instance.
* @return This builder.
*/
public Builder setNotification(AndroidNotification notification) {
this.notification = notification;
return this;
}

/**
* Creates a new {@link AndroidConfig} instance from the parameters set on this builder.
*
* @return A new {@link AndroidConfig} instance.
* @throws IllegalArgumentException If any of the parameters set on the builder are invalid.
*/
public AndroidConfig build() {
return new AndroidConfig(this);
}
}
}
Loading