早些時候Cordova想要透過Azure Notification Hub做推播功能,可以透過azure-mobile-apps-js-client
和phonegap-plugin-push
套件,並搭配Azure Mobile app就可以輕鬆做到Push Message功能,不過,今日這樣組合已經無法幫Cordova在不寫程式情況下透過Azure Mobile App向Notification Hub註冊Device,主要是Azure Mobile App跟Notification Hub整合後的註冊device API似乎不見了,所以,使用上會出現下面錯誤
“Failed to load resource: the server responded with a status of 404 - Cannot GET /push/installations/xxxxx(it’s a guid string)”
因此,就必須在Mobile App上自己開發這一段API
安裝套件
要讓我們開發的API跟Azure Notification Hub做溝通,須安裝Microsoft.Azure.Notification
套件,並建立一個Notification class來設定API與Notification Hub連線資訊1
2
3
4
5
6
7
8
9
10
11
public class NotificationHub
{
public static NotificationHub Instance = new NotificationHub();
public NotificationHubClient Hub { get ; set ; }
private NotificationHub ( )
{
Hub = NotificationHubClient.CreateClientFromConnectionString("DefaultFullSharedAccessSignature" ,"Notification Name" );
}
}
幫你的Device註冊到Azure Notification Hub的資訊如下:
PNS 識別碼:主要是要跟推播平台註冊的ID,每一個平台的編碼方式不同
註冊ID :主要是跟zure Notification Hub註冊的識別碼
標記 :在這邊我們主要是定義pns識別碼 的使用者識別,好讓我們後續能做個別推播的發送
其中,PNS
和註冊ID
在當你APP被移除重新安裝時候,在Notification Hub上的這兩個資訊就會被更新
取得註冊ID 這邊先把Notification Hub通道建立起來1
2
3
4
5
private NotificationHubClient hub;
public PushController ( )
{
hub = NotificationHub.Instance.Hub;
}
當Device註冊到Azure Notification Hub時,Notification Hub本身就會自動幫你建立一個Mapping表,透過下面程式可以列出所有註冊在Notification Hub上資訊,不過,有一點要注意,就是當你的Notification Hub在註冊推播平台的憑證換掉後,這些資訊似乎會消失1
2
3
4
5
6
7
8
9
var allRegistrations = await hub.GetAllRegistrationsAsync(0 );
var continuationToken = allRegistrations.ContinuationToken;
var registrationDescriptionsList = new List<RegistrationDescription>(allRegistrations);
while (!string .IsNullOrWhiteSpace(continuationToken))
{
var otherRegistrations = await hub.GetAllRegistrationsAsync(continuationToken, 0 );
registrationDescriptionsList.AddRange(otherRegistrations);
continuationToken = otherRegistrations.ContinuationToken;
}
因此,為了避免同一個PNS會出現不同註冊ID,當需要取得註冊ID時候,可以把PNS
碼帶入,如果有相同的PNS碼就會沿用當下的註冊ID,如果還是擔心,也可以加入Tag資訊做判斷1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[HttpPost]
public async Task<string > GetNhRegistrationid (string PNS = null )
{
string newNhRegistid = null ;
if (PNS != null )
{
var registrations = await hub.GetRegistrationsByChannelAsync(PNS, 100 );
foreach (RegistrationDescription registration in registrations)
{
if (newNhRegistid == null )
{
newNhRegistid = registration.RegistrationId;
}
else
{
await hub.DeleteRegistrationAsync(registration);
}
}
}
if (newNhRegistid == null )
{
newNhRegistid = await hub.CreateRegistrationIdAsync();
}
return newNhRegistid;
}
當有了註冊ID之後,接下來就是要註冊Device,所以,要建立註冊Device資訊的Class,這邊的Tag如果不是只有一組,可以使用陣列1
2
3
4
5
6
public class DeviceRegist
{
public string Platform { get ; set ; }
public string PNS { get ; set ; }
public string Tags { get ; set ; }
}
其中,Platform簡稱是不能亂定義,資訊可以參考Notification Hub對於各個推播平台的簡稱
在deviceupdate.Platform中,會針對不同推播平台使用不同的方法去註冊PNS,而各大推播平台基本上也只認得PNS識別碼,所以,不僅要把註冊資訊註冊到Hub中,也必須把PNS註冊註冊到推播平台上1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
[HttpPut]
public async Task<HttpResponseMessage> RegisteredDevice (string inRegistrationId, DeviceRegist deviceupdate )
{
RegistrationDescription registration = null ;
switch (deviceupdate.Platform)
{
case "apns" :
registration = new AppleRegistrationDescription(deviceupdate.PNS);
break ;
case "gcm" :
registration = new GcmRegistrationDescription(deviceupdate.PNS);
break ;
default :
throw new HttpResponseException(HttpStatusCode.BadRequest);
}
registration.RegistrationId = inRegistrationId;
registration.Tags = new HashSet<string >();
registration.Tags.Add(deviceupdate.Tags);
try
{
await hub.CreateOrUpdateRegistrationAsync(registration);
}
catch (MessagingException ex)
{
ReturnGoneIfHubResponseIsGone(ex);
}
catch (Exception ex1)
{
throw ex1;
}
return Request.CreateResponse(HttpStatusCode.OK);
}
以上方式基本上就可以自行做到透過API將資訊註冊到Hub中,如果要想自己去刪掉推播平台上的PNS碼,可以自行加入下面這一段1
2
3
4
5
6
[HttpDelete]
public async Task<HttpResponseMessage> Delete (string PNS )
{
await hub.DeleteRegistrationAsync(PNS);
return Request.CreateResponse(HttpStatusCode.OK);
}
此外,因為註冊資訊可能因為憑證被換掉或是更新導致Mapping被清掉,所以,這邊其實可以把這資訊存放到資料庫中,這樣就可以避免資訊消失,另外,因為PNS
和註冊ID
這資訊格式基本上是固定,為了讓推播更有效率或是能分門別類的推播,就必須依賴Tag管理,利用Tag資訊去分門別類推播
這樣做完之後,Cordova要怎樣呼叫呢?我們依舊還是可以azure-mobile-apps-js-client
和phonegap-plugin-push
套件處理,只是不能採用原本文件上的寫法1
2
3
4
push.on('registration' , function (data ) {
console .log('PNS data' +data.registrationId);
azureClient.push.register('gcm' , data.registrationId);
});
這部分可以參考
Cordova 無法使用mobile service plugin結合azure PushNotification 的替代方案
這篇的解法