Repository: firebase/firebase-admin-java
Pull request #303 (2019-08-23 22:51:03)

Update to fix broken link
Hey there! So you want to contribute to a Firebase SDK? 
Before you file this pull request, please read these guidelines:

### Discussion

  * Read the contribution guidelines (CONTRIBUTING.md).
  * If this has been discussed in an issue, make sure to link to the issue here. 
    If not, go file an issue about this **before creating a pull request** to discuss.

### Testing

  * Make sure all existing tests in the repository pass after your change.
  * If you fixed a bug or added a feature, add a new test to cover your code.

### API Changes

  * At this time we cannot accept changes that affect the public API.  If you'd like to help 
    us make Firebase APIs better, please propose your change in an issue so that we 
    can discuss it together.



Patch:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index b60aba8..467c0d3 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -15,7 +15,7 @@ We get lots of those and we love helping you, but GitHub is not the best place f
 which just ask about usage will be closed. Here are some resources to get help:
 
 - Go through the [guides](https://firebase.google.com/docs/admin/setup/)
-- Read the full [API reference](https://firebase.google.com/docs/reference/admin/java/)
+- Read the full [API reference](https://firebase.google.com/docs/reference/admin#java)
 
 If the official documentation doesn't help, try asking a question on the
 [Firebase Google Group](https://groups.google.com/forum/#!forum/firebase-talk/) or one of our
diff --git a/src/main/java/com/google/firebase/FirebaseApp.java b/src/main/java/com/google/firebase/FirebaseApp.java
index f69ee36..c60f0ad 100644
--- a/src/main/java/com/google/firebase/FirebaseApp.java
+++ b/src/main/java/com/google/firebase/FirebaseApp.java
@@ -132,7 +132,6 @@ public class FirebaseApp {
    *
    * @throws IllegalStateException if the default app was not initialized.
    */
-  @Nullable
   public static FirebaseApp getInstance() {
     return getInstance(DEFAULT_APP_NAME);
   }
diff --git a/src/main/java/com/google/firebase/messaging/AndroidNotification.java b/src/main/java/com/google/firebase/messaging/AndroidNotification.java
index 064f493..ef286d4 100644
--- a/src/main/java/com/google/firebase/messaging/AndroidNotification.java
+++ b/src/main/java/com/google/firebase/messaging/AndroidNotification.java
@@ -66,6 +66,9 @@ public class AndroidNotification {
   
   @Key("channel_id")
   private final String channelId;
+  
+  @Key("image")
+  private final String image;
 
   private AndroidNotification(Builder builder) {
     this.title = builder.title;
@@ -97,6 +100,7 @@ public class AndroidNotification {
       this.titleLocArgs = null;
     }
     this.channelId = builder.channelId;
+    this.image = builder.image;
   }
 
   /**
@@ -122,6 +126,7 @@ public class AndroidNotification {
     private String titleLocKey;
     private List<String> titleLocArgs = new ArrayList<>();
     private String channelId;
+    private String image;
 
     private Builder() {}
 
@@ -292,6 +297,18 @@ public class AndroidNotification {
       return this;
     }
 
+    /**
+     * Sets the URL of the image that is going to be displayed in the notification. When provided, 
+     * overrides the imageUrl set via {@link Notification}.
+     *
+     * @param imageUrl URL of the image that is going to be displayed in the notification.
+     * @return This builder.
+     */
+    public Builder setImage(String imageUrl) {
+      this.image = imageUrl;
+      return this;
+    }
+
     /**
      * Creates a new {@link AndroidNotification} instance from the parameters set on this builder.
      *
diff --git a/src/main/java/com/google/firebase/messaging/ApnsFcmOptions.java b/src/main/java/com/google/firebase/messaging/ApnsFcmOptions.java
index 708c0b5..46bc570 100644
--- a/src/main/java/com/google/firebase/messaging/ApnsFcmOptions.java
+++ b/src/main/java/com/google/firebase/messaging/ApnsFcmOptions.java
@@ -24,10 +24,14 @@ public final class ApnsFcmOptions {
 
   @Key("analytics_label")
   private final String analyticsLabel;
+  
+  @Key("image")
+  private final String image;
 
   private ApnsFcmOptions(Builder builder) {
     FcmOptionsUtil.checkAnalyticsLabel(builder.analyticsLabel);
     this.analyticsLabel = builder.analyticsLabel;
+    this.image = builder.image;
   }
 
   /**
@@ -53,6 +57,8 @@ public final class ApnsFcmOptions {
 
     private String analyticsLabel;
 
+    private String image;
+
     private Builder() {}
 
     /**
@@ -64,6 +70,15 @@ public final class ApnsFcmOptions {
       return this;
     }
 
+    /**
+     * @param imageUrl URL of the image that is going to be displayed in the notification.
+     * @return This builder
+     */
+    public Builder setImage(String imageUrl) {
+      this.image = imageUrl;
+      return this;
+    }
+
     /**
      * Creates a new {@link ApnsFcmOptions} instance from the parameters set on this builder.
      *
diff --git a/src/main/java/com/google/firebase/messaging/Notification.java b/src/main/java/com/google/firebase/messaging/Notification.java
index eaa1e14..866c066 100644
--- a/src/main/java/com/google/firebase/messaging/Notification.java
+++ b/src/main/java/com/google/firebase/messaging/Notification.java
@@ -29,6 +29,9 @@ public class Notification {
 
   @Key("body")
   private final String body;
+  
+  @Key("image")
+  private final String image;
 
   /**
    * Creates a new {@code Notification} using the given title and body.
@@ -37,8 +40,20 @@ public class Notification {
    * @param body Body of the notification.
    */
   public Notification(String title, String body) {
+    this(title, body, null);
+  }
+  
+  /**
+   * Creates a new {@code Notification} using the given title, body, and image.
+   *
+   * @param title Title of the notification.
+   * @param body Body of the notification.
+   * @param imageUrl URL of the image that is going to be displayed in the notification.
+   */
+  public Notification(String title, String body, String imageUrl) {
     this.title = title;
     this.body = body;
+    this.image = imageUrl;
   }
 
 }


Test patch:
diff --git a/src/test/java/com/google/firebase/messaging/FirebaseMessagingIT.java b/src/test/java/com/google/firebase/messaging/FirebaseMessagingIT.java
index 751ba8b..494923f 100644
--- a/src/test/java/com/google/firebase/messaging/FirebaseMessagingIT.java
+++ b/src/test/java/com/google/firebase/messaging/FirebaseMessagingIT.java
@@ -34,6 +34,7 @@ public class FirebaseMessagingIT {
   private static final String TEST_REGISTRATION_TOKEN =
       "fGw0qy4TGgk:APA91bGtWGjuhp4WRhHXgbabIYp1jxEKI08ofj_v1bKhWAGJQ4e3arRCWzeTfHaLz83mBnDh0a"
           + "PWB1AykXAVUUGl2h1wT4XI6XazWpvY7RBUSYfoxtqSWGIm2nvWh2BOP1YG501SsRoE";
+  private static final String TEST_IMAGE_URL = "https://example.com/image.png";
 
   @BeforeClass
   public static void setUpClass() {
@@ -44,7 +45,7 @@ public class FirebaseMessagingIT {
   public void testSend() throws Exception {
     FirebaseMessaging messaging = FirebaseMessaging.getInstance();
     Message message = Message.builder()
-        .setNotification(new Notification("Title", "Body"))
+        .setNotification(new Notification("Title", "Body", TEST_IMAGE_URL))
         .setAndroidConfig(AndroidConfig.builder()
             .setRestrictedPackageName("com.google.firebase.testing")
             .build())
diff --git a/src/test/java/com/google/firebase/messaging/MessageTest.java b/src/test/java/com/google/firebase/messaging/MessageTest.java
index 6744a35..2db28d5 100644
--- a/src/test/java/com/google/firebase/messaging/MessageTest.java
+++ b/src/test/java/com/google/firebase/messaging/MessageTest.java
@@ -36,6 +36,10 @@ import org.junit.Test;
 
 public class MessageTest {
 
+  private static final String TEST_IMAGE_URL = "https://example.com/image.png";
+  private static final String TEST_IMAGE_URL_ANDROID = "https://example.com/android-image.png";
+  private static final String TEST_IMAGE_URL_APNS = "https://example.com/apns-image.png";
+
   @Test(expected = IllegalArgumentException.class)
   public void testMessageWithoutTarget() {
     Message.builder().build();
@@ -698,6 +702,76 @@ public class MessageTest {
     }
   }
 
+  @Test
+  public void testImageInNotification() throws IOException {
+    Message message = Message.builder()
+        .setNotification(new Notification("title", "body", TEST_IMAGE_URL))
+        .setTopic("test-topic")
+        .build();
+    Map<String, String> data = ImmutableMap.of(
+        "title", "title", "body", "body", "image", TEST_IMAGE_URL);
+    assertJsonEquals(ImmutableMap.of("topic", "test-topic", "notification", data), message);
+  }
+
+  @Test
+  public void testImageInAndroidNotification() throws IOException {
+    Message message = Message.builder()
+        .setNotification(new Notification("title", "body", TEST_IMAGE_URL))
+        .setAndroidConfig(AndroidConfig.builder()
+            .setNotification(AndroidNotification.builder()
+                .setTitle("android-title")
+                .setBody("android-body")
+                .setImage(TEST_IMAGE_URL_ANDROID)
+                .build())
+            .build())
+        .setTopic("test-topic")
+        .build();
+    Map<String, Object> notification = ImmutableMap.<String, Object>builder()
+        .put("title", "title")
+        .put("body", "body")
+        .put("image", TEST_IMAGE_URL)
+        .build();
+    Map<String, Object> androidConfig = ImmutableMap.<String, Object>builder()
+        .put("notification", ImmutableMap.<String, Object>builder()
+            .put("title", "android-title")
+            .put("body", "android-body")
+            .put("image", TEST_IMAGE_URL_ANDROID)
+            .build())
+        .build();
+    assertJsonEquals(ImmutableMap.of(
+        "topic", "test-topic", "notification", notification, "android", androidConfig), message);
+  }
+  
+  @Test
+  public void testImageInApnsNotification() throws IOException {
+    Message message = Message.builder()
+        .setTopic("test-topic")
+        .setNotification(new Notification("title", "body", TEST_IMAGE_URL))
+        .setApnsConfig(
+            ApnsConfig.builder().setAps(Aps.builder().build())
+                .setFcmOptions(ApnsFcmOptions.builder().setImage(TEST_IMAGE_URL_APNS).build())
+                .build()).build();
+
+    ImmutableMap<String, Object> notification =
+        ImmutableMap.<String, Object>builder()
+            .put("title", "title")
+            .put("body", "body")
+            .put("image", TEST_IMAGE_URL)
+            .build();
+    ImmutableMap<String, Object> apnsConfig =
+        ImmutableMap.<String, Object>builder()
+            .put("fcm_options", ImmutableMap.of("image", TEST_IMAGE_URL_APNS))
+            .put("payload", ImmutableMap.of("aps", ImmutableMap.of()))
+            .build();
+    ImmutableMap<String, Object> expected =
+        ImmutableMap.<String, Object>builder()
+            .put("topic", "test-topic")
+            .put("notification", notification)
+            .put("apns", apnsConfig)
+            .build();
+    assertJsonEquals(expected, message);
+  }
+
   private static void assertJsonEquals(
       Map expected, Object actual) throws IOException {
     assertEquals(expected, toMap(actual));