Skip to content

Commit b901e62

Browse files
authored
Merge pull request #19 from firebase/hkj-fcm-part4
Implemented APNs Support in the API
2 parents 70efb05 + ae1e80c commit b901e62

File tree

8 files changed

+1400
-23
lines changed

8 files changed

+1400
-23
lines changed

FirebaseAdmin/FirebaseAdmin.Tests/Messaging/MessageTest.cs

Lines changed: 758 additions & 0 deletions
Large diffs are not rendered by default.

FirebaseAdmin/FirebaseAdmin/Messaging/AndroidNotification.cs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -135,21 +135,15 @@ internal AndroidNotification CopyAndValidate()
135135
};
136136
if (copy.Color != null && !Regex.Match(copy.Color, "^#[0-9a-fA-F]{6}$").Success)
137137
{
138-
throw new ArgumentException("Color must be in the form #RRGGBB");
138+
throw new ArgumentException("Color must be in the form #RRGGBB.");
139139
}
140-
if (copy.TitleLocArgs != null && copy.TitleLocArgs.Any())
140+
if (copy.TitleLocArgs?.Any() == true && string.IsNullOrEmpty(copy.TitleLocKey))
141141
{
142-
if (string.IsNullOrEmpty(copy.TitleLocKey))
143-
{
144-
throw new ArgumentException("TitleLocKey is required when specifying TitleLocArgs");
145-
}
142+
throw new ArgumentException("TitleLocKey is required when specifying TitleLocArgs.");
146143
}
147-
if (copy.BodyLocArgs != null && copy.BodyLocArgs.Any())
144+
if (copy.BodyLocArgs?.Any() == true && string.IsNullOrEmpty(copy.BodyLocKey))
148145
{
149-
if (string.IsNullOrEmpty(copy.BodyLocKey))
150-
{
151-
throw new ArgumentException("BodyLocKey is required when specifying BodyLocArgs");
152-
}
146+
throw new ArgumentException("BodyLocKey is required when specifying BodyLocArgs.");
153147
}
154148
return copy;
155149
}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
// Copyright 2018, Google Inc. All rights reserved.
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+
using System;
16+
using System.Collections.Generic;
17+
using System.Linq;
18+
using Google.Apis.Json;
19+
using Newtonsoft.Json;
20+
21+
namespace FirebaseAdmin.Messaging
22+
{
23+
/// <summary>
24+
/// Represents the APNS-specific options that can be included in a <see cref="Message"/>. Refer
25+
/// to <see href="https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html">
26+
/// APNs documentation</see> for various headers and payload fields supported by APNS.
27+
/// </summary>
28+
public sealed class ApnsConfig
29+
{
30+
private ApnsPayload _payload = new ApnsPayload();
31+
32+
/// <summary>
33+
/// A collection of APNs headers.
34+
/// </summary>
35+
[JsonProperty("headers")]
36+
public IReadOnlyDictionary<string, string> Headers { get; set; }
37+
38+
/// <summary>
39+
/// The <code>aps</code> dictionary to be included in the APNs payload.
40+
/// </summary>
41+
[JsonIgnore]
42+
public Aps Aps
43+
{
44+
get
45+
{
46+
return Payload.Aps;
47+
}
48+
set
49+
{
50+
Payload.Aps = value;
51+
}
52+
}
53+
54+
/// <summary>
55+
/// APNs payload as accepted by the FCM backend servers.
56+
/// </summary>
57+
[JsonProperty("payload")]
58+
private ApnsPayload Payload
59+
{
60+
get
61+
{
62+
if (_payload.Aps != null && _payload.CustomData?.ContainsKey("aps") == true)
63+
{
64+
throw new ArgumentException("Multiple specifications for ApnsConfig key: aps");
65+
}
66+
return _payload;
67+
}
68+
set
69+
{
70+
_payload = value;
71+
}
72+
}
73+
74+
/// <summary>
75+
/// A collection of arbitrary key-value data to be included in the APNs payload.
76+
/// </summary>
77+
[JsonIgnore]
78+
public IDictionary<string, object> CustomData
79+
{
80+
get
81+
{
82+
return Payload.CustomData;
83+
}
84+
set
85+
{
86+
Payload.CustomData = value;
87+
}
88+
}
89+
90+
/// <summary>
91+
/// Copies this APNs config, and validates the content of it to ensure that it can be
92+
/// serialized into the JSON format expected by the FCM service.
93+
/// </summary>
94+
internal ApnsConfig CopyAndValidate()
95+
{
96+
var copy = new ApnsConfig()
97+
{
98+
Headers = this.Headers?.Copy(),
99+
Payload = this.Payload.CopyAndValidate(),
100+
};
101+
return copy;
102+
}
103+
}
104+
105+
/// <summary>
106+
/// The APNs payload object as expected by the FCM backend service.
107+
/// </summary>
108+
internal sealed class ApnsPayload
109+
{
110+
[JsonProperty("aps")]
111+
internal Aps Aps { get; set; }
112+
113+
[JsonExtensionData]
114+
internal IDictionary<string, object> CustomData { get; set; }
115+
116+
/// <summary>
117+
/// Copies this APNs payload, and validates the content of it to ensure that it can be
118+
/// serialized into the JSON format expected by the FCM service.
119+
/// </summary>
120+
internal ApnsPayload CopyAndValidate()
121+
{
122+
var copy = new ApnsPayload()
123+
{
124+
CustomData = this.CustomData?.ToDictionary(e => e.Key, e => e.Value),
125+
};
126+
var aps = this.Aps;
127+
if (aps == null && copy.CustomData?.ContainsKey("aps") == false)
128+
{
129+
throw new ArgumentException("Aps dictionary is required in ApnsConfig");
130+
}
131+
copy.Aps = aps?.CopyAndValidate();
132+
return copy;
133+
}
134+
}
135+
}

0 commit comments

Comments
 (0)