I'm writting sms application, which get from server by restapi number and message where to send and also receive sms from receipent. I have issue when received sms has more than 160 characters. And issue is when I have more than 160 characters to send by SMS.
Receive sms code:
public override void OnReceive(Context context, Intent intent)
{
if (intent.HasExtra("pdus"))
{
var smsArray = (Java.Lang.Object[])intent.Extras.Get("pdus");
foreach(var item in smsArray)
{
var sms = SmsMessage.CreateFromPdu((byte[])item);
SendReceivedStatus(sms.OriginatingAddress, sms.MessageBody);
}
}
}
SendReceivedStatus(sms.OriginatingAddress, sms.MessageBody);
It's a my method that convert to json receipentNumber and message.
Now my send sms code:
var sent = PendingIntent.GetBroadcast(Application.Context, 0, new Intent("SMS_SENT"), 0);
SmsManager.Default.SendTextMessage(responseModel.receipent, null, responseModel.message, sent, null);
protected override void OnResume()
{
base.OnResume();
var smsSentReceiver = new SMSSentReceiver();
RegisterReceiver(smsSentReceiver, new IntentFilter("SMS_SENT"));
}
public override void OnReceive(Context context, Intent intent)
{
switch ((int)ResultCode)
{
case (int)Result.Ok:
SenderActivity.resultsms = true;
SendStatus();
break;
case (int)SmsResultError.GenericFailure:
SenderActivity.resultsms = false;
SendStatus();
break;
case (int)SmsResultError.NoService:
SenderActivity.resultsms = false;
SendStatus();
break;
case (int)SmsResultError.NullPdu:
SenderActivity.resultsms = false;
SendStatus();
break;
case (int)SmsResultError.RadioOff:
SenderActivity.resultsms = false;
SendStatus();
break;
}
}
How to pack these messages?
Since SmsMessage.CreateFromPdu((byte[])) is deprecated since Android API level 19, here I also provide method to receive message more than 160 characters after KitKat version, here is my demo:
[BroadcastReceiver(Enabled = true, Label = "SMS Receiver")]
[IntentFilter(new[] { "android.provider.Telephony.SMS_RECEIVED" })]
public class SMSReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
Bundle bundle = intent.Extras;
if (bundle != null)
{
if (Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat)
{
SmsMessage[] msgs = Telephony.Sms.Intents.GetMessagesFromIntent(intent);
var smstext = new StringBuilder();
foreach (var msg in msgs)
{
smstext.Append(msg.DisplayMessageBody.ToString());
}
Console.WriteLine(smstext.ToString());//output the received sms
}
else
{
var smsArray = (Java.Lang.Object[])bundle.Get("pdus");
SmsMessage[] messages = new SmsMessage[smsArray.Length];
for (int i = 0; i < smsArray.Length; i++)
{
messages[i] = SmsMessage.CreateFromPdu((byte[])smsArray[i]);
}
StringBuilder content = new StringBuilder();
if (messages.Length > 0)
{
foreach (var message in messages)
{
content.Append(message.DisplayMessageBody.ToString());
}
}
Console.WriteLine(content.ToString());//output the received sms
}
}
Toast.MakeText(context, "Received intent!", ToastLength.Short).Show();
}
}
I've tested my demo on Android 6.0 device and it works fine, I now can't find a Android 4.0 device for testing, but I think the method should work here. Any problem about this issue, please leave a comment.
Related
we have implement file chooser for web view. it works successfully when attachment is selected, but fails when cancelled without file specification. The file chooser just stops to react on click
any help is appreciated. Thanks
we use chrome client. it works fine if in all cases, file selection is listed. but even from the first file selection is cancelled, no longer file chooser will work. It is Xamarin.Android app based fully on webview
Our code is:
protected override void OnActivityResult(int requestCode, Result resultCode, Intent intent)
{
if (requestCode == FILECHOOSER_RESULTCODE)
{
if (null == _mUploadMessage)
return;
// Check that the response is a good one
if (resultCode == Result.Ok)
{
Android.Net.Uri[] results = null;
if (intent == null)
{
// If there is not data, then we may have taken a photo
if (mCameraPhotoPath != null)
{
results = new Android.Net.Uri[] { Android.Net.Uri.Parse(mCameraPhotoPath) };
}
}
else
{
if (intent.DataString != null)
{
results = new Android.Net.Uri[] { Android.Net.Uri.Parse(intent.DataString) };
}
}
_mUploadMessage.OnReceiveValue(results);
_mUploadMessage = null;
}
}
}
Chrome client:
var chrome = new FileChooserWebChromeClient((uploadMsg) =>
{
_mUploadMessage = uploadMsg;
mCameraPhotoPath = null;
Intent takePictureIntent = new Intent(Android.Provider.MediaStore.ActionImageCapture);
//Create the File where the photo should go
File photoFile = null;
try
{
string folder = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
photoFile = new File(folder, "image" + DateTime.Now.Millisecond + ".png");
takePictureIntent.PutExtra("PhotoPath", mCameraPhotoPath);
}
catch (IOException ex)
{
// Error occurred while creating the File
System.Console.WriteLine("" + ex.ToString());
}
// Continue only if the File was successfully created
if (photoFile != null)
{
mCameraPhotoPath = "file:" + photoFile.AbsolutePath;
takePictureIntent.PutExtra(Android.Provider.MediaStore.ExtraOutput,
Android.Net.Uri.FromFile(photoFile));
}
else
{
takePictureIntent = null;
}
Intent contentSelectionIntent = new Intent(Intent.ActionGetContent);
contentSelectionIntent.AddCategory(Intent.CategoryOpenable);
contentSelectionIntent.SetType("image/*");
Intent[] intentArray;
if (takePictureIntent != null)
{
intentArray = new Intent[] { takePictureIntent };
}
else
{
intentArray = new Intent[0];
}
Intent chooserIntent = new Intent(Intent.ActionChooser);
chooserIntent.PutExtra(Intent.ExtraIntent, contentSelectionIntent);
chooserIntent.PutExtra(Intent.ExtraTitle, this.GetStringFromResource(Resource.String.chose_photo));
chooserIntent.PutExtra(Intent.ExtraInitialIntents, intentArray);
base.StartActivityForResult(chooserIntent, HarmonyAndroid.AndroidMainActivity.FILECHOOSER_RESULTCODE);
});
return chrome;
Part 2
class FileChooserWebChromeClient : WebChromeClient
{
Action<IValueCallback> callback;
public FileChooserWebChromeClient(Action<IValueCallback> callback)
{
this.callback = callback;
}
public override bool OnShowFileChooser(WebView webView, IValueCallback filePathCallback, FileChooserParams fileChooserParams)
{
callback(filePathCallback);
return true;
}
public override void OnCloseWindow(WebView window)
{
base.OnCloseWindow(window);
}
}
Part 3
webView.ImprovePerformance();
webView.SetWebViewClient(new HomeWebViewClient(customWebViewClientListener, clientId));
webView.SetWebChromeClient(chrome);
webView.Settings.JavaScriptEnabled = true;
webView.Settings.DomStorageEnabled = true;
webView.SetDownloadListener(new CustomDownloadListener(activity, customDownloadListener));
webView.AddJavascriptInterface(new JavaScriptToCSharpCommunication(activity, javaScriptToCSharpCommunicationListener), Constants.JS_CSHARP_COMMUNICATOR_NAME);
Try to give a null object to the uri callback, when the resultCode is not RESULT_OK.
add in your OnActivityResult method:
if (resultCode != Result.Ok)
{
_mUploadMessage.OnReceiveValue(null);
_mUploadMessage = null;
return;
}
Cannot send text from TIdTCPServer To TIdTCPClient, the server hanging (Not Responding), it just freezes when trying to send text to the client.
I Started Recently using Indy TIdTCPClient and TIdTCPServer, i have the client application working well when sending and receiving response from the server form,
then issue is from the server it doesn't send data, and when i try to send data like Indy creators provided in their Doc, it just freezes and then stops responding (crashes) :(, the weird thing is that the server sends back the response on Execute Event, and not sending data with my send function, so here is my code that i use:
Server Execute Event:
void __fastcall TServerMain::IdTCPServer1Execute(TIdContext *AContext)
{
UnicodeString uMessage;
uMessage = AContext->Connection->IOHandler->ReadLn();
MessageDisplay1->Lines->Add(uMessage);
AContext->Connection->IOHandler->WriteLn("Response OK!"); // i can receive the response from the client
}
Server Send Function:
void TServerMain::itsSendMessage(TIdTCPServer *itsName, UnicodeString uMessage) {
TIdContextList *Clients;
TIdContext *icContext;
if ( uMessage.Length() != 0 && itsName->Active ) {
Clients = itsName->Contexts->LockList();
for (int i = 0; i < Clients->Count; i++) {
icContext = (TIdContext*)Clients->Items[i];
icContext->Connection->IOHandler->WriteLn(uMessage);
}
itsName->Contexts->UnlockList();
}
} // this function doesn't send text to the clients however, it just hangs the application for ever.
Additional Note: The TIdTCPServer stops sending text even from it's OnExecute event when a client is disconnects!
UPDATE:
void __fastcall TMyContext::AddToQueue(TStream *AStream)
{
TStringList *queue = this->FQueue->Lock();
try {
queue->AddObject("", AStream);
this->FMessageInQueue = true;
}
__finally
{
this->FQueue->Unlock();
}
}
void __fastcall TMyContext::CheckQueue()
{
if ( !this->FMessageInQueue )
return;
std::unique_ptr<TStringList> temp(new TStringList);
TStringList *queue = this->FQueue->Lock();
try {
temp->OwnsObjects = true;
temp->Assign(queue);
queue->Clear();
this->FMessageInQueue = false;
}
__finally
{
this->FQueue->Unlock();
}
for (int i = 0; i < temp->Count; i++) {
this->Connection->IOHandler->Write( static_cast<TStream*>(temp->Objects[i]), static_cast<TStream*>(temp->Objects[i])->Size, true );
}
}
Server Send Function:
void __fastcall TServerMain::IdSendMessage(TIdTCPServer *IdTCPServer, TStream *AStream)
{
if ( !IdTCPServer->Active )
return;
TIdContextList *Clients = IdTCPServer->Contexts->LockList();
try {
for (int i = 0; i < Clients->Count; i++) {
static_cast<TMyContext*>(static_cast<TIdContext*>(Clients->Items[i]))->AddToQueue(AStream);
}
}
__finally
{
IdTCPServer->Contexts->UnlockList();
}
}
Client Receive Function:
void __fastcall TReadingThread::Receive() {
TMemoryStream * ms = new TMemoryStream();
this->IdTCPClient1->IOHandler->ReadStream(ms);
ms->Position = 0;
ClientMain->Image1->Picture->Bitmap->LoadFromStream(ms);
delete ms;
}
This function is Synchronized in a TThread.
This is how i send a TBitmap using TMemoryStream:
void __fastcall TServerMain::CaptureDesktop()
{
// Capture Desktop Canvas
HDC hdcDesktop;
TBitmap *bmpCapture = new TBitmap();
TMemoryStream *Stream = new TMemoryStream();
try {
bmpCapture->Width = Screen->Width;
bmpCapture->Height = Screen->Height;
hdcDesktop = GetDC(GetDesktopWindow());
BitBlt(bmpCapture->Canvas->Handle, 0,0,Screen->Width, Screen->Height, hdcDesktop, 0,0, SRCCOPY);
bmpCapture->SaveToStream(Stream);
Stream->Position = 0;
IdSendMessage(IdTCPServer1, Stream);
}
__finally
{
ReleaseDC(GetDesktopWindow(), hdcDesktop);
delete bmpCapture;
delete Stream;
}
}
TIdTCPServer is a multi-threaded component, which you are not accounting for propery.
The server's various events are fired in the context of internal worker threads, not in the context the main UI thread. Your OnExecute code is not syncing with the main UI thread when accessing MessageDisplay1, which can cause all kinds of problems, including but not limited to deadlocks. You MUST sync with the main UI thread, such as with TThread::Synchronize() or TThread::Queue(). For example:
void __fastcall TServerMain::IdTCPServer1Execute(TIdContext *AContext)
{
String Message = AContext->Connection->IOHandler->ReadLn();
// see http://docwiki.embarcadero.com/RADStudio/en/How_to_Handle_Delphi_Anonymous_Methods_in_C%2B%2B
TThread::Queue(nullptr, [](){ MessageDisplay1->Lines->Add(Message); });
AContext->Connection->IOHandler->WriteLn(_D("Response OK!"));
}
Also, you have 2 threads (whichever thread is calling itsSendMessage(), and the OnExecute thread) that are not syncing with each other, so they can potentially write text to the same client at the same time, overlapping each other's text and thus corrupting your communications. When sending unsolicited messages from the server to a client, I usually recommend (depending on circumstances) that you queue the messages and let the client thread's OnExecute code decide when it is safe to send the queue. Another reason to do this is to avoid deadlocks if one client becomes blocked, you don't want to block access to other clients. Do as much per-client work in the client's own OnExecute event as you can. For example:
class TMyContext : public TIdServerContext
{
private:
TIdThreadSafeStringList *FQueue;
bool FMsgInQueue;
public:
__fastcall TMyContext(TIdTCPConnection *AConnection, TIdYarn *AYarn, TIdContextThreadList *AList = nullptr)
: TIdServerContext(AConnection, AYarn, AList)
{
FQueue = new TIdThreadSafeStringList;
}
__fastcall ~TMyContext()
{
delete FQueue;
}
void AddToQueue(const String &Message)
{
TStringList *queue = FQueue->Lock();
try
{
queue->Add(Message);
FMsgInQueue = true;
}
__finally
{
FQueue->Unlock();
}
}
void CheckQueue()
{
if (!FMsgInQueue)
return;
std::unique_ptr<TStringList> temp(new TStringList);
TStringList *queue = FQueue->Lock();
try
{
temp->Assign(queue);
queue->Clear();
FMsgInQueue = false;
}
__finally
{
FQueue->Unlock();
}
Connection->IOHandler->Write(temp.get());
}
bool HasPendingData()
{
TIdIOHandler *io = Connection->IOHandler;
bool empty = io->InputBufferIsEmpty();
if (empty)
{
io->CheckForDataOnSource(100);
io->CheckForDisconnect();
empty = io->InputBufferIsEmpty();
}
return !empty;
}
};
__fastcall TServerMain::TServerMain(...)
{
IdTCPServer1->ContextClass = __classid(TMyContext);
...
}
void __fastcall TServerMain::IdTCPServer1Execute(TIdContext *AContext)
{
TMyContext *ctx = static_cast<TMyContext*>(AContext);
ctx->CheckQueue();
if (!ctx->HasPendingData())
return;
String Message = AContext->Connection->IOHandler->ReadLn();
TThread::Queue(nullptr, [](){ MessageDisplay1->Lines->Add(Message); });
AContext->Connection->IOHandler->WriteLn(_D("Response OK!"));
}
void TServerMain::itsSendMessage(TIdTCPServer *itsName, const String &Message)
{
if ( Message.IsEmpty() || !itsName->Active )
return;
TIdContextList *Clients = itsName->Contexts->LockList();
try
{
for (int i = 0; i < Clients->Count; ++i)
{
static_cast<TMyContext*>(static_cast<TIdContext*>(Clients->Items[i]))->AddToQueue(Message);
}
}
__finally
{
itsName->Contexts->UnlockList();
}
}
According this it seems it's impossible to show welcome messages in Microsoft teams while using ActivityTypes.ConversationUpdate last year..
I wonder whether it is possible now. Any suggestion?
I have tried this but it seems not work.
private Activity HandleSystemMessage(Activity message)
{
if (message.Type == ActivityTypes.DeleteUserData)
{
// Implement user deletion here
// If we handle user deletion, return a real message
}
else if (message.Type == ActivityTypes.ConversationUpdate)
{
// Handle conversation state changes, like members being added and removed
// Use Activity.MembersAdded and Activity.MembersRemoved and Activity.Action for info
// Not available in all channels
if (message.Conversation.IsGroup == true)
{
bool addedBot = false;
Activity newMessage = new Activity();
string res = "";
for (int i = 0; i < message.MembersAdded.Count; i++)
{
if (message.MembersAdded[i].Id == message.Recipient.Id)
{
addedBot = true;
break;
}
}
if (message.MembersAdded.Count > 0 && addedBot == false)
{
ConnectorClient connector = new ConnectorClient(new Uri(message.ServiceUrl));
Activity reply = message.CreateReply("test");
connector.Conversations.ReplyToActivityAsync(reply);
}
}
else
{
ConnectorClient connector = new ConnectorClient(new Uri(message.ServiceUrl));
Activity reply = message.CreateReply("test");
connector.Conversations.ReplyToActivityAsync(reply);
}
}
else if (message.Type == ActivityTypes.ContactRelationUpdate)
{
// Handle add/remove from contact lists
// Activity.From + Activity.Action represent what happened
}
else if (message.Type == ActivityTypes.Typing)
{
// Handle knowing tha the user is typing
}
//else if (message.Type == ActivityTypes.Ping)
//{
//}
return null;
}
2018/09/06
It works.
My code works. But it seems it's impossible to send other existing users 1to1 message when bot is added.
How to use Broadcast Reciever in Xamarin.Form reference to this forum http://forums.xamarin.com/discussion/7070/how-to-prevent-sms-going-to-inbox
the class
public class SmsReceiver : BroadcastReceiver
{
public static readonly string IntentAction = "android.provider.Telephony.SMS_RECEIVED";
public override void OnReceive(Context context, Intent intent)
{
InvokeAbortBroadcast();
try
{
if (intent.Action != IntentAction) return;
var bundle = intent.Extras;
if (bundle == null) return;
var pdus = bundle.Get("pdus");
var castedPdus = JNIEnv.GetArray<Java.Lang.Object>(pdus.Handle);
var msgs = new SmsMessage[castedPdus.Length];
var sb = new StringBuilder();
String sender = null;
for (var i = 0; i < msgs.Length; i++)
{
var bytes = new byte[JNIEnv.GetArrayLength(castedPdus[i].Handle)];
JNIEnv.CopyArray(castedPdus[i].Handle, bytes);
msgs[i] = SmsMessage.CreateFromPdu(bytes);
if (sender == null) sender = msgs[i].OriginatingAddress;
sb.Append(string.Format("SMS From: {0}{1}Body: {2}{1}", msgs[i].OriginatingAddress,
System.Environment.NewLine, msgs[i].MessageBody));
}
if (sender != null && sender.EndsWith("09068100820"))
{
// Process our sms...
// SMS.updateMessageBox("\nFrom: " + msg.getOriginatingAddress() + "\n" +
//"Message: " + msg.getMessageBody() + "\n");
/*((SMS) context).delete();*/
Toast.MakeText(context, "IsOrderedBroadcast :" + IsOrderedBroadcast.ToString() + "\n" + sb.ToString(), ToastLength.Long).Show();
}
else
{
ClearAbortBroadcast();
}
}
catch (Exception ex)
{
Toast.MakeText(context, ex.Message, ToastLength.Long).Show();
}
}
}
How to implement this class in Xamarin.Form and get the incoming SMS, Thanks in advance and Good Day :D
From Android 4.4, You can't do any kind of operation on SMS except just reading it if your app isn't the default SMS app.
If your app is default sms app and you want to block sender or whatever then put your SmsReceiver in Android Project and register it in Application class.
I don't think you need to do anything in Forms Project.
This is a fairly long piece of code but I am getting nowhere with this and cannot see any issues, although I am new to using notification hubs. I am trying to register for targeted notifications (the logged on user) using the notification hub in Azure. After the registration, a test notification is sent.
The issue I am having is that sometimes the notification is sent to the device, and sometimes it is not. It mostly isn't but occasionally when I step through the code on the server, i will get the notification on the emulator come through. Once when I deployed the app to my phone the notification came though on the emulator! I cannot discover a pattern.
My Controller class looks like this;
private NotificationHelper hub;
public RegisterController()
{
hub = NotificationHelper.Instance;
}
public async Task<RegistrationDescription> Post([FromBody]JObject registrationCall)
{
var obj = await hub.Post(registrationCall);
return obj;
}
And the helper class (which is used elsewhere so is not directly in the controller) looks like this;
public static NotificationHelper Instance = new NotificationHelper();
public NotificationHubClient Hub { get; set; }
// Create the client in the constructor.
public NotificationHelper()
{
var cn = "<my-cn>";
Hub = NotificationHubClient.CreateClientFromConnectionString(cn, "<my-hub>");
}
public async Task<RegistrationDescription> Post([FromBody] JObject registrationCall)
{
// Get the registration info that we need from the request.
var platform = registrationCall["platform"].ToString();
var installationId = registrationCall["instId"].ToString();
var channelUri = registrationCall["channelUri"] != null
? registrationCall["channelUri"].ToString()
: null;
var deviceToken = registrationCall["deviceToken"] != null
? registrationCall["deviceToken"].ToString()
: null;
var userName = HttpContext.Current.User.Identity.Name;
// Get registrations for the current installation ID.
var regsForInstId = await Hub.GetRegistrationsByTagAsync(installationId, 100);
var updated = false;
var firstRegistration = true;
RegistrationDescription registration = null;
// Check for existing registrations.
foreach (var registrationDescription in regsForInstId)
{
if (firstRegistration)
{
// Update the tags.
registrationDescription.Tags = new HashSet<string>() {installationId, userName};
// We need to handle each platform separately.
switch (platform)
{
case "windows":
var winReg = registrationDescription as MpnsRegistrationDescription;
winReg.ChannelUri = new Uri(channelUri);
registration = await Hub.UpdateRegistrationAsync(winReg);
break;
case "ios":
var iosReg = registrationDescription as AppleRegistrationDescription;
iosReg.DeviceToken = deviceToken;
registration = await Hub.UpdateRegistrationAsync(iosReg);
break;
}
updated = true;
firstRegistration = false;
}
else
{
// We shouldn't have any extra registrations; delete if we do.
await Hub.DeleteRegistrationAsync(registrationDescription);
}
}
// Create a new registration.
if (!updated)
{
switch (platform)
{
case "windows":
registration = await Hub.CreateMpnsNativeRegistrationAsync(channelUri,
new string[] {installationId, userName});
break;
case "ios":
registration = await Hub.CreateAppleNativeRegistrationAsync(deviceToken,
new string[] {installationId, userName});
break;
}
}
// Send out a test notification.
await SendNotification(string.Format("Test notification for {0}", userName), userName);
return registration;
And finally, my SendNotification method is here;
internal async Task SendNotification(string notificationText, string tag)
{
try
{
var toast = PrepareToastPayload("<my-hub>", notificationText);
// Send a notification to the logged-in user on both platforms.
await NotificationHelper.Instance.Hub.SendMpnsNativeNotificationAsync(toast, tag);
//await hubClient.SendAppleNativeNotificationAsync(alert, tag);
}
catch (ArgumentException ex)
{
// This is expected when an APNS registration doesn't exist.
Console.WriteLine(ex.Message);
}
}
I suspect the issue is in my phone client code, which is here and SubscribeToService is called immediately after WebAPI login;
public void SubscribeToService()
{
_channel = HttpNotificationChannel.Find("mychannel");
if (_channel == null)
{
_channel = new HttpNotificationChannel("mychannel");
_channel.Open();
_channel.BindToShellToast();
}
_channel.ChannelUriUpdated += async (o, args) =>
{
var hub = new NotificationHub("<my-hub>", "<my-cn>");
await hub.RegisterNativeAsync(args.ChannelUri.ToString());
await RegisterForMessageNotificationsAsync();
};
}
public async Task RegisterForMessageNotificationsAsync()
{
using (var client = GetNewHttpClient(true))
{
// Get the info that we need to request registration.
var installationId = LocalStorageManager.GetInstallationId(); // a new Guid
var registration = new Dictionary<string, string>()
{
{"platform", "windows"},
{"instId", installationId},
{"channelUri", _channel.ChannelUri.ToString()}
};
var request = new HttpRequestMessage(HttpMethod.Post, new Uri(ApiUrl + "api/Register/RegisterForNotifications"));
request.Content = new StringContent(JsonConvert.SerializeObject(registration), Encoding.UTF8, "application/json");
string message;
try
{
HttpResponseMessage response = await client.SendAsync(request);
message = await response.Content.ReadAsStringAsync();
}
catch (Exception ex)
{
message = ex.Message;
}
_registrationId = message;
}
}
Any help would be greatly appriciated as I have been stuck on this now for days! I know this is a lot of code to paste up here but it is all relevant.
Thanks,
EDIT: The SubscribeToService() method is called when the user logs in and authenticates with the WebAPI. The method is here;
public async Task<User> SendSubmitLogonAsync(LogonObject lo)
{
_logonObject = lo;
using (var client = GetNewHttpClient(false))
{
var logonString = String.Format("grant_type=password&username={0}&password={1}", lo.username, lo.password);
var sc = new StringContent(logonString, Encoding.UTF8);
var response = await client.PostAsync("Token", sc);
if (response.IsSuccessStatusCode)
{
_logonResponse = await response.Content.ReadAsAsync<TokenResponseModel>();
var userInfo = await GetUserInfoAsync();
if (_channel == null)
SubscribeToService();
else
await RegisterForMessageNotificationsAsync();
return userInfo;
}
// ...
}
}
I have solved the issue. There are tons of fairly poorly organised howto's for azure notification hubs and only one of them has this note toward the bottom;
NOTE:
You will not receive the notification when you are still in the app.
To receive a toast notification while the app is active, you must
handle the ShellToastNotificationReceived event.
This is why I was experiencing intermittent results, as i assumed you would still get a notification if you were in the app. And this little note is pretty well hidden.
Have you used proper tag / tag expressions while register/send the message. Also, Where are you storing the id back from the notification hub. It should be used when you update the channel uri (it will expire).
I would suggest to start from scratch.
Ref: http://msdn.microsoft.com/en-us/library/dn530749.aspx