How to display SignalR Notification when Browser is in Minimize Mode - signalr

I have created notification apps using SignalR in Blazor Web Application.It works fine as per our requirement, but when I minimize Web Browser then the notification Toast message showing within that application (in minimize mode).I would like to know how to display notification Toast message when browser is minimize (Notification Toast should display in task bar)
C# Code:-
protected async override Task OnInitializedAsync()
{
base.OnInitialized();
bpmHubConnection = new HubConnectionBuilder()
.WithUrl(ONEERP.Web.Models.SessionManager.BpmApiBaseAddress + "hubs/BPMBroadCastHub")
.Build();
bpmHubConnection.On<int, int, string, string>("SendNotification", (userGroupID, userID, name, message) =>
{
if (SessionManager.UserID == userID)
{
CallLoadNotification();
StateHasChanged();
}
});
}
.razor Code :-
<SfToast ID="toastNotification" ShowCloseButton="true" #ref="ToastNotificationObj" Title="Notification" Content="#ToastNotificationContent" CssClass="#ToastNotificationStyle" Timeout=#ConstantClass.ToastTimeout Icon="e-meeting">
<ToastPosition X="Right" Y="Bottom"></ToastPosition>
</SfToast>

Technically what you're trying to do is impossible. You do have one option, using Browser notifications (see link below). Rather than using toast notifications, you could "push" a notification to the browser. The user will have to allow it, but it sounds like you're developing something for a relatively small set of users.
https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API/Using_the_Notifications_API

Related

How to handle user interaction with new Bluetooth prompt in iOS13?

"There’s a new key for the Info.plist file: NSBluetoothAlwaysUsageDescription, which you can use to explain how and why your app uses Bluetooth. In contrast to the existing NSBluetoothPeripheralUsageDescription, the new description will be shown as part of the new pop-up, and also in the Settings app on the Bluetooth Privacy screens."
After updating to iOS 13, our app experienced crashes, as I'm sure many did. Our problem was due to not including the newly required bluetooth key in the Xamarin.iOS projects Info.plist file.
However after adding this upon loading the first "action" that occurs is presenting the user with the new Bluetooth access prompt.
We aren't clearly seeing how to capture the response to this prompt. In-fact after this prompt is interacted with the app has no "return" point as it were. Can't quite find a break-point for the prompt interaction / result handling and our app never returns from the prompt. It's running but the next "action" to occur never happens.
So- how to capture/handle user's interaction with the new Bluetooth prompt in iOS 13?
NOTE*: To be absolutely transparent - our application doesn't initialize any instance of CBCentralManager rather it takes advantage of a native framework that itself utilizes Bluetooth LE internally (out of our control).
Our case might be quite unique but for those experiencing this implement CBCentralManager and utilize its UpdatedState method to capture user interaction with the newly presented Bluetooth dialogue.
Initialization called in page creation of our Apps MainPage
BleManager = new BluetoothManager();
Class
using System;
using CoreBluetooth;
namespace MyApp.iOS.Classes
{
public class BluetoothManager
{
public CBCentralManager CentralBleManager
{
get { return this.bleCntrlMgr; }
}
protected CBCentralManager bleCntrlMgr;
protected CBCentralManagerDelegate bleMgrDel;
public BluetoothManager()
{
this.bleCntrlMgr = new CoreBluetooth.CBCentralManager();
this.bleCntrlMgr.UpdatedState += BleMgr_UpdatedState;
}
private void BleMgr_UpdatedState(object sender, EventArgs e)
{
Console.WriteLine("UpdatedState: {0}", bleCntrlMgr.State);
if (bleCntrlMgr.State == CBCentralManagerState.PoweredOn
|| bleCntrlMgr.State == CBCentralManagerState.PoweredOff
|| bleCntrlMgr.State == CBCentralManagerState.Resetting
|| bleCntrlMgr.State == CBCentralManagerState.Unauthorized
|| bleCntrlMgr.State == CBCentralManagerState.Unsupported)
{
/* return point */
// i.e.: CallMethod();
}
else if (bleCntrlMgr.State == CBCentralManagerState.Unknown)
{
/* <-- request access --> */
}
}
}
}

Android <-> iOS Bluetooth LE application, can't write to characteristic

I'm developing a ble-based native local multiplayer plugin for Unity (for both Android and iOS). I use a single service, with a single characteristic with rw permissions. I've managed to make Android<->Android and iOS<->iOS work all right, but I'm having a rough time trying to make Android<->iOS work. Specifically, it's the 'iOS as Peripheral, Android as Central' combination the one that keeps me up at night. After many hours of fiddling, testing, googling and trying, I have very much pinned down the problem to this:
From the Android side, if I don't subscribe to the characteristic, a call to BluetoothGatt#writeCharacteristic(characteristic), like this:
String str = "the data";
xferCharacteristic.setValue(str.getBytes("UTF-8"));
mGatt.writeCharacteristic(xferCharacteristic);
will return 'true' and succeed, and the peripheralManager:didReceiveWriteRequests: callback will be called on the iOS side where I can manipulate the precious received data as I see fit. So far so good. But, if I try to update a characteristic from the iOS end, the Android central won't get notified (the callback BluetoothGattCallback#onCharacteristicChanged should be called, but it isn't), since it did not subscribe to the characteristic.
If I make the Android central subscribe to the characteristic offered by the iOS peripheral, by means of this section of code:
First, connect to the iOS peripheral with
public void onScanResult(int callbackType, ScanResult result) {
BluetoothDevice btDevice = result.getDevice();
mGatt = device.connectGatt(appContext, false, mGattCallback);
...
with mGattCallback an instance of BLEGattCallback which will handle the onServicesDiscovered callback:
public class BLEGattCallback extends BluetoothGattCallback {
private static final UUID CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
List<BluetoothGattService> services = gatt.getServices();
for(BluetoothGattService s : services) { // foreach service...
if(UUID.fromString(MyServiceUUID).equals(s.getUuid())) { // just the one I want...
List<BluetoothGattCharacteristic> characteristics = s.getCharacteristics();
for(BluetoothGattCharacteristic c : characteristics) { // foreach characteristic...
if(c.getUuid().toString().equals(BLEManager.FGUUIDXferQueueString)) { // just the char. I want...
c.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
for (BluetoothGattDescriptor descriptor : c.getDescriptors()) {
if(descriptor.getUuid().equals(CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID)) {
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
}
gatt.setCharacteristicNotification(c, true);
}
}
}
}
}
This makes the Android central correctly subscribe for the characteristic (the callback method peripheralManager:central:didSubscribeToCharacteristic: is called on the iOS peripheral), BUT, if i do this, the call to mGatt.writeCharacteristic(xferCharacteristic) will return 'false' and no data will be written to the peripheral, so it's a kind of can-only-write or can-only-notify-update situation.
I have unsuccessfully tried to find out the meaning of writeCharacteristic returning 'false', to no avail (seriously, an error code would help a lot).
I've tried a lot of different combinations, values, etc... but, bottom line: as soon as I call gatt.writeDescriptor subsequent calls to writeCharacteristic will fail, and if I don't call gatt.writeDescriptor the android central won't subscribe.
I'm pretty much stuck here. Any help appreciated. Thanks a lot.
Classic issue. You must wait for the operation to complete before you can issue another one. See Android BLE BluetoothGatt.writeDescriptor() return sometimes false.
Thanks to the received hint, this issue has been solved. These are the changes I made to the code:
The Android client must wait for the writeDescriptor(...) request to finish before issuing a writeCharacteristic(...) command. For that, I had to #Override the method onDescriptorWrite on my BLEGattCallback class, which will be called when the writeDescriptor operation completes. I moved my first writeCharacteristic(...) call here, and now the information is sent to the iOS endpoint (the rest must be flow-controlled). So I'm very happy.

Prism navigation from within a Service only working when not navigating back to much

I have a Prism Xamarin.Forms App created with the Prism Template Pack (2.0.7).
All packages are up to date:
Xamarin.Forms v2.5.0.91635
Xamarin.Android.* v26.1.0.1
Prism.DryIoc.Forms v7.0.0.168-pre (Could not update to v7.0.0.269-pre due to a NullReferenceException in Android Renderer on startup, however my main application is using 269-pre without that problem)
I hosted the sample Application on https://github.com/dernippel/PrismNavApp
I have the following components:
Module "Attachments" (a Prism Module)
Module "Viewer" (a Prism Module)
Service "AttachmentService" registered with the Container with an Interface as Singleton
They should do this:
The AttachmentsPage (from the AttachmentsModule) lists some objects
Selecting one Attachment
AttachmentPageViewModel calls the "OpenAttachment"-Method of the Attachment Service
The Method determines the correct ViewerPage by type and uses the Prism-NavigationService to navigate directly to the Page (in the sample this is the "ImageViewerPage" of the ViewerModule)
This is only working when you do the following navigation:
MainPage -> AttachmentsPage -> ViewerPage -> (back Arrow) AttachmentsPage -> ViewerPage (and so on)
But if you navigate back to MainPage navigation to ViewerPage isn't working anymore:
MainPage -> AttachmentsPage -> ViewerPage -> (back Arrow) AttachmentsPage -> (back Arrow) MainPage -> AttachmentsPage -> (nothing happens anymore when tap on Button to navigate to ViewerPage)
The AttachmentsService gets the NavigationService via Constructor injection and navigates this way:
public AttachmentService(INavigationService navigationService)
{
this.navigationService = navigationService;
}
public async void OpenAttachmentWithViewer(object attachment)
{
// ToDo: handle parameter proberbly
var attachmentType = "image";
// select correct viewer
if (attachmentType == "image")
{
// navigate to image viewer
var navParams = new NavigationParameters();
navParams.Add("object",attachment);
var navTask = this.navigationService.NavigateAsync(
"ImageViewerPage",
navParams,
useModalNavigation: false);
await navTask;
var result = navTask.Status;
Debug.WriteLine($"Navigation State is {result}");
}
}
I tried to check the navigation Task result status, it is always "RanToCompletion".
Modifying the AttachmentsPageViewModel to navigate directly with the Prism NavigationService instead using the Service doesn't cause this behavior:
private void OnOpenAttachment()
{
// ToDo: get the selected attachment
object selectedAttachment = null;
// navigating inside a service -- not working when navigating back to MainPage
//this.attachmentService.OpenAttachmentWithViewer(selectedAttachment);
// navigation from view model -- working
var navParams = new NavigationParameters();
navParams.Add("object", selectedAttachment);
this.navigationService.NavigateAsync("ImageViewerPage", navParams, useModalNavigation: false);
}
Hint: I switched with my Main-Application from PCL-based to the new .NETStandard based solution and already had a similar functionality working successfully using Prism v6.3.0.1. This functionality is not even navigating once since the port.
Actually I don't know how to solve this.
Is it possible to have a look into the Prism NavigationService to determine why the navigation is not happen?
I didn't find any known bug in the Prism Repository yet.
You can't use the NavigationService in another service, especially if that service is a singleton. Navigation in Xamarin.Forms is specific to a Page, and only works in context of an associated page. Instead, your service should return a result and you should navigate from your VM based on that result. Don't try to navigate from within a service.

Updating UI BeginInvokeOnMainThread not reflecting immediately

I am showing activity indicator after clicking login button until redirecting the user to another page, to make them understand some progress is going on. But after clicking login button Activity Indicator is not shown immediately, it is shown after few seconds,
Why its so? To reduce that delay only I am putting activity indicator...
My Code:
async void loginButtonGesture_Tapped(object sender, EventArgs e)
{
Device.BeginInvokeOnMainThread(() =>
{
loadingPanel.IsRunning = true;
loadingPanel.IsVisible = true;
});
}
Does the method have to be async void? It seems like this particular scheduling anything on the main thread shouldn't need to be async. Try that to see if it changes anything. Also you could try to set breakpoints on the Device.BeginInvokeOnMainThread line, and the loadingPanel.IsRunning... line to see where the delay happens.
First of all, loginButtonGesture_Tapped() event handler is triggered by UI thread so you don't need to use Device.BeginInvokeOnMainThread(), it is already in UI thread. But since you used Device.BeginInvokeOnMainThread() here, the reason for the delay is because on Android, your code inside of BeginInvokeOnMainThread() is added to MainLooper's message queue,(your code is not executed immediately) and is executed when the UI thread is scheduled to handle its messages.
The detailed answer can be found in Xamarin document:
For iOS:
IOSPlatformServices.BeginInvokeOnMainThread() Method simply calls NSRunLoop.Main.BeginInvokeOnMainThread
public void BeginInvokeOnMainThread(Action action)
{
NSRunLoop.Main.BeginInvokeOnMainThread(action.Invoke);
}
https://developer.xamarin.com/api/member/Foundation.NSObject.BeginInvokeOnMainThread/p/ObjCRuntime.Selector/Foundation.NSObject/
You use this method from a thread to invoke the code in the specified object that is exposed with the specified selector in the UI thread. This is required for most operations that affect UIKit or AppKit as neither one of those APIs is thread safe.
The code is executed when the main thread goes back to its main loop for processing events.
For Android:
Many People think on Xamarin.Android BeginInvokeOnMainThread() method use Activity.runOnUiThread(), BUT this is NOT the case, and there is a difference between using runOnUiThread() and Handler.Post():
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);//<-- post message delays action until UI thread is scheduled to handle messages
} else {
action.run();//<--action is executed immediately if current running thread is UI thread.
}
}
The actual implementation of Xamarin.Android BeginInvokeOnMainThread() method can be found in AndroidPlatformServices.cs class
public void BeginInvokeOnMainThread(Action action)
{
if (s_handler == null || s_handler.Looper != Looper.MainLooper)
{
s_handler = new Handler(Looper.MainLooper);
}
s_handler.Post(action);
}
https://developer.android.com/reference/android/os/Handler.html#post(java.lang.Runnable)
As you can see, you action code is not executed immediately by Handler.Post(action). It is added to the Looper's message queue, and is handled when the UI thread's scheduled to handle its message.

Implement push notification server in php

This is my first post, sorry my English
Hello every one. I am a new programmer in PHP and i would like to use Zend Mobile Framework to implement my push notificator server.
I'm searching how to implement the tomcat project used in
http://developer.android.com/guide/google/gcm/demo.html
but written in PHP.
In the code most below I written the used sources.
When I call the submit button, always have response with InvalidRegistration error.
Can anyone see where the error?
Thank You very much
http://pastebin.com/MauzLX71
According with Android GCM's architectural overview you have an invalidRegistration error when:
Invalid Registration ID Check the formatting of the registration ID
that you pass to the server. Make sure it matches the registration ID
the phone receives in the com.google.android.c2dm.intent.REGISTRATION
intent and that you're not truncating it or adding additional
characters. Happens when error code is InvalidRegistration.
Check the official GCM documentaion here, please.
One of the things that you are likely having happen here is the following:
Your code is actually processing and attempting to send a message prior to your call of sendPush which may be causing part of the issue.
I've modified the code and had put the registration id in there: http://pastebin.com/NhrD5N6i
Did you sign up for an API key and replace that portion in the code?
In the demo client application; it shows how to actually leverage the registration; see my comment on the following GitHub issue: https://github.com/mwillbanks/Zend_Mobile/issues/16
Your server needs to have the registration id from the device; this is likely what you do not have.
One way of getting the registration ID is on the onRegistered call inside the client app, do a Log.i("MY_APP_TAG", regId); then look at the logcat output.
Android Example
public class GCMIntentService extends GCMBaseIntentService {
public GCMIntentService() {
super(Constants.SENDER_ID);
}
#Override
protected void onRegistered(Context context, String regId) {
Log.i("MY_APP_TAG", "Registered: " + regId);
}
#Override
protected void onUnregistered(Context context, String regId) {
// write a call here to send the regId to your server and unregister it
}
#Override
protected void onMessage(Context context, Intent intent) {
Log.i("MY_APP_TAG", "Received message!");
// grabbing data looks like the following; the assumption
// is title is part of the data string.
String title = intent.getExtras().getString("title");
}
}
*Zend_Mobile_Push_Gcm Example*
See the updated link (http://pastebin.com/NhrD5N6i) I provided of your pasted code; you will want to use the registration ID above in the textbox.

Resources