I have the configuration in Unity and Firebase correctly, I receive the notifications on the mobile when I send them through the firebase panel, when I tap on the notification the app opens without problems, but when I try to retrieve the message data such as the title in the app, it crashes and closes. When I retrieve only the token, it does show it.
This is the code that I am using, if anyone knows what it is due to, I would appreciate if you have the solution, the app does not generate any error in the log, it simply closes when I add the line of code: textDisplay_2.text = notification.Title ;
`
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class PushNot : MonoBehaviour
{
public TextMeshProUGUI textDisplay_1;
public TextMeshProUGUI textDisplay_2;
// Start is called before the first frame update
public void Start()
{
textDisplay_1.text = "inicia app";
Firebase.Messaging.FirebaseMessaging.TokenReceived += OnTokenReceived;
Firebase.Messaging.FirebaseMessaging.MessageReceived += OnMessageReceived;
}
public void OnTokenReceived(object sender, Firebase.Messaging.TokenReceivedEventArgs token)
{
UnityEngine.Debug.Log("Received Registration Token: " + token.Token);
textDisplay_1.text = token.Token;
}
public void OnMessageReceived(object sender, Firebase.Messaging.MessageReceivedEventArgs e)
{
UnityEngine.Debug.Log("Received a new message from: " + e.Message.From);
var notification = e.Message.Notification;
textDisplay_2.text = notification.Title;
}
}
`
I need to retrieve the data of the push message such as the title and body and display them in two text components, the app closes when placing the line of code textDisplay_2.text = notification.Title; without showing any error in the log.
Related
I am trying to create a chat application in a Unity game. So basically in one instance of the game if someone sends a message , all the other open instances of the game should get the message.
I successfully created a self-hosted SignalR 2 server using this tutorial
The code for the console app is as follows:
using System;
using Microsoft.AspNet.SignalR;
using Microsoft.Owin.Hosting;
using Owin;
using Microsoft.Owin.Cors;
namespace SignalRSelfHost
{
class Program
{
static void Main(string[] args)
{
// This will *ONLY* bind to localhost, if you want to bind to all addresses
// use http://*:8080 to bind to all addresses.
// See http://msdn.microsoft.com/library/system.net.httplistener.aspx
// for more information.
string url = "http://localhost:8080";//a web application of type Startup is started at the specified URL (http://localhost:8080).
using (WebApp.Start(url))
{
Console.WriteLine("Server running on {0}", url);
Console.ReadLine();
}
}
}
class Startup
{// the class containing the configuration for the SignalR server ,which creates routes for any Hub objects in the project.
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR();
}
}
public class MyHub : Hub
{//the SignalR Hub class that the application will provide to clients.
public void Send(string name, string message)
{
Clients.All.addMessage(name, message);//clients will call to broadcast a message to all other connected clients.
}
}
}
I created a dummy Unity game as of now. There are the username input field and chat input field. Next to the chat input field there is a send button. So the person enters his/her name and enters something into the chat and all running instances of the game should receive the message , but I am not able to achieve that thing
The script for this is attached to a empty GameObject SignalRManager. The code is as follows:
using System.Collections.Generic;
using UnityEngine;
using Microsoft.AspNet.SignalR.Client;
using UnityEngine.UI;
using System;
using TMPro;
public class SignalRManager : MonoBehaviour
{
string url = "http://localhost:8080";
HubConnection connection;
[SerializeField] private GameObject ChatMessage;
[SerializeField] private GameObject UserName;
// Start is called before the first frame update
void Start()
{
connection = new HubConnection(url);
connection.Start();
connection.StateChanged += connection_StateChanged;
}
private void connection_StateChanged(StateChange state)
{
if(state.NewState== ConnectionState.Connected)
{
Debug.Log("Connected to Server");
}
if(state.NewState == ConnectionState.Disconnected)
{
Debug.Log("Disconnected from Server");
}
}
public void OnClickSendChatButton()
{
string message= ChatMessage.GetComponent<TMP_InputField>().text;
string userName= UserName.GetComponent<TMP_InputField>().text;
}
private void OnDisable()
{
connection.StateChanged -= connection_StateChanged;
}
}
I am able to connect to the server as the log message appears , but dont know what to write to send message to the server. Also how do I receive the message from the server as well
I tried to use a function called connection.Send(), but it is not accepting two arguments. I tried to look into many tutorials ,but many are for asp.netcore Signal r , but I need it for asp.net signalR because thats my requirement.
<<<<--------edit------>>>
I was able to send data to the server but I am not able to receive data from the server on my Unity game. The updated code is as follows:
using System.Collections.Generic;
using UnityEngine;
using Microsoft.AspNet.SignalR.Client;
using UnityEngine.UI;
using System;
using TMPro;
public class SignalRManager : MonoBehaviour
{
string url = "http://localhost:8080";
HubConnection connection;
IHubProxy hubProxy;
[SerializeField] private GameObject ChatMessage;
[SerializeField] private GameObject UserName;
[SerializeField] private TextMeshProUGUI OutputText;
// Start is called before the first frame update
void Start()
{
connection = new HubConnection(url);//Create a connection for the SignalR server
hubProxy = connection.CreateHubProxy("MyHub");//Get a proxy object that will be used to interact with the specific hub on the server.There may be many hubs hosted on the server, so provide the type name for the hub
connection.Start();
connection.StateChanged += connection_StateChanged;
OutputText.text = "";
}
private void OnReceivedMessageFromServer(string name, string message)
{
OutputText.text = OutputText.text+name + ":" + message + "\n";
Debug.Log(OutputText.text + name + ":" + message + "\n");
}
private void connection_StateChanged(StateChange state)
{
if(state.NewState== ConnectionState.Connected)
{
Debug.Log("Connected to Server");
}
if(state.NewState == ConnectionState.Disconnected)
{
Debug.Log("Disconnected from Server");
}
}
public void OnClickSendChatButton()
{
string message= ChatMessage.GetComponent<TMP_InputField>().text;
string userName= UserName.GetComponent<TMP_InputField>().text;
hubProxy.On<string, string>("addMessage", OnReceivedMessageFromServer);//register hub events (methods invoked by the hub). The following code registers a handler method for ChatMessage event.
hubProxy.Invoke("Send", userName, message);
}
private void OnDisable()
{
connection.StateChanged -= connection_StateChanged;
}
}
The callBack OnReceivedMessageFromServer is not invoked. Can anyone help me here?
I have no idea how to pass a parameter from MainActivity.cs
this code from App.cs
protected override void OnResume(int notificationId)
{
MainPage = new AppShell(notificationId);
}
I plan to pass a number in the "notificationId" parameter. To find a row in the database by "notificationId".
If you're integrating push notification(e,g Azure notification hubs) into your application , OnResume is not the appropriate method to handle this .
Actually every push notification kit has its own trigger method when receiving notification (or tapping on the notification alert) .
For example , we can handle the notification in method OnPushNotificationReceived with Azure notification .
// Set the delegate for receiving messages
NotificationHub.SetListener(new SampleNotificationListener());
// The notification listener implementation
public class SampleNotificationListener : Java.Lang.Object, INotificationListener
{
public void OnPushNotificationReceived(Context context, INotificationMessage message)
{
Console.WriteLine($"Message received with title {message.Title} and body {message.Body}");
}
}
Refer to https://github.com/Azure/azure-notificationhubs-xamarin#getting-started-with-xamarinandroid.
Then we can use Messaging Center to send the data to Forms project if you want .
Something like
//Android
public void OnPushNotificationReceived(Context context, INotificationMessage message)
{
MessagingCenter.Send<object,int >(this, "Hi",notificationId);
}
//Forms App.cs
MessagingCenter.Subscribe<object,int> (this, "Hi", (sender,id) =>
{
MainPage = new AppShell(id);
});
I have a MainPage in PCL which then navigates to a Platform Specific
Login Page on LoginButton Click Event
The LoginPage is inherited from
platform specific PageRenderer as it needs platform specific
Authentication to Social Providers (Facebook, Google, Twitter,
Microsoft, etc.)
I am using Xamarin.Auth to do the authentication.
Inside the OnElementChanged event of the LoginPage, it instantiates
the OAuth2Authenticator object.
Upon successful instantiation (based
on provider and app details), it needs to call the UI of the specific
provider.
To do that, I call the auth.GetUI where auth is
Xamarin.Auth.OAuth2Authenticator object.
I have two questions:
In UWP, how do I navigate to the provider login UI? More specifically, what is the equivalent in UWP of the following code snippets in iOS and Android? In iOS, the following code is used:
PresentViewController(auth.GetUI(), true, null);
where auth is Xamarin.Auth.OAuth2Authenticator object.
In Android the following is used:
activity.StartActivity(auth.GetUI(activity));
I am looking for the equivalent code in UWP. Please bear in mind that these calls are made from the LoginPage which is derived from Platform specific PageRenderer
How do I navigate back to my MainPage (which is in PCL) upon successful authentication?
The code is based off of a sample from the following source:
http://www.c-sharpcorner.com/article/oauth-login-authenticating-with-identity-provider-in-xamarin-forms/
Here is my code for the LoginPage:
using System;
using Valufy;
using Xamarin.Forms.Platform.UWP;
using System.ComponentModel;
using Valufy.UWP;
using Valufy.AuthConfiguration;
using Xamarin.Forms;
[assembly: ExportRenderer(typeof(ProviderLoginPage), typeof(LoginRenderer))]
namespace Valufy.UWP
{
class LoginRenderer: PageRenderer
{
protected override void OnElementChanged (ElementChangedEventArgs<Xamarin.Forms.Page> e)
{
base.OnElementChanged(e);
//Get and Assign ProviderName from ProviderLoginPage
ProviderLoginPage loginPage = (ProviderLoginPage)Element;
string providername = loginPage.ProviderName;
//Create OauthProviderSetting class with Oauth Implementation .Refer Step 6
OAuthProviderSetting oauth = new OAuthProviderSetting();
Xamarin.Auth.OAuth2Authenticator auth = oauth.LoginWithProvider(providername);
// After facebook,google and all identity provider login completed
auth.Completed += Auth_Completed;
Type page_type = auth.GetUI();
//////THIS IS WHERE I AM STUCK...HOW DO I GO TO THE PROVIDER AUTH UI ////////////
//this.Frame.Navigate(page_type, auth);
//parentPage.Navigation.PushModalAsync(auth.GetUI());
}
}
private void Auth_Completed(object sender, Xamarin.Auth.AuthenticatorCompletedEventArgs e)
{
if (e.IsAuthenticated)
{
OAuthConfig.User = new UserDetails();
// Get and Save User Details
OAuthConfig.User.Token = e.Account.Properties["oauth_token"];
OAuthConfig.User.TokenSecret = e.Account.Properties["oauth_token_secret"];
OAuthConfig.User.TwitterId = e.Account.Properties["user_id"];
OAuthConfig.User.ScreenName = e.Account.Properties["screen_name"];
/////NOW, HOW GO I GO BACK TO THE CALLING PAGE IN PCL ///////////////////
}
else
{
// The user cancelled
/////NOW, HOW GO I GO BACK TO THE CALLING PAGE IN PCL ///////////////////
}
}
}
}
Here is the code to navigate to the provider login for UWP:
WindowsPage windowsPage = new WindowsPage();
_frame = windowsPage.Frame;
if (_frame == null)
{
_frame = new Windows.UI.Xaml.Controls.Frame
{
Language = global::Windows.Globalization.ApplicationLanguages.Languages[0]
};
windowsPage.Content = _frame;
SetNativeControl(windowsPage);
}
Type pageType = auth.GetUI();
_frame.Navigate(pageType, auth);
To navigate back to my page upon successful authentication, here is the code:
private async void Auth_Completed(object sender, Xamarin.Auth.AuthenticatorCompletedEventArgs e)
{
if (e.IsAuthenticated)
{
var request = new OAuth2Request("GET", new Uri("https://login.microsoftonline.com/common/oauth2/V2.0/token?oauth2_access_token=" + e.Account.Properties["access_token"]), null, e.Account);
try
{
string response = await MSGetUserInfo(e.Account);
}
catch (System.OperationCanceledException)
{
}
catch (Exception ex)
{
}
this.Element.Navigation.PushModalAsync(new MainPage());
}
else
{
// The user cancelled
}
}
1- In UWP, how do I navigate to the provider login UI
You need to create a UWP Page object, the same object you are will use to display in the renderer is the one you will use to do the navigation.
Type page_type = auth.GetUI();
page = new MyUWPLoginPage();
page.Frame.Navigate(page_type, auth);
2- How do I navigate back to my MainPage (which is in PCL) upon successful authentication?
There are many ways to do this, the easiest one is creating a public method in your ProviderLoginPage class and from the renderer classes call this method and pass-in the parameters.
public class ProviderLoginPage: ContentPage
{
......
public void AuthenticationCompleted(object sender, Xamarin.Auth.AuthenticatorCompletedEventArgs e)
{
// Do your logic
}
}
In your Renderer using the Element:
private void Auth_Completed(object sender, Xamarin.Auth.AuthenticatorCompletedEventArgs e)
{
var xamElement = Element as ProviderLogin;
xamElement?.AuthenticationCompleted(sender, e);
}
Move all the logic to the PCL class so you don't have to repeat it on each renderer.
This should help.
I'm using quartz in an asp.net site and I'm using it to fire off a longer background task. I want to be able to use a timer or jquery to call the job and get back status and progress info similar to how I was doing it before. Here is code that I was using:
protected void Timer1_Tick(object sender, EventArgs e)
{
if (MyTaskManager.Instance.IsTaskRunning)
{
if (MyTaskManager.Instance.TotalItems > 0) ProgressLabel.Text = string.Format(ProgressLabel.Text, MyTaskManager.Instance.TotalItems, MyTaskManager.Instance.ItemsProcessed);
else ProgressLabel.Text = string.Format("Records Processed: {0}", MyTaskManager.Instance.ItemsProcessed);
}
else
{
Timer1.Enabled = false;
}
}
Has anyone done this that could point me in the right direction?
It might not be what you're looking for but I've used SignalR with Quartz.Net and it works great.
I've published a simple application in my repository.
You have to create a custom Hub which you will use to interact with your ASP.NET page.
Your (quartz.net) job will interact your ASP.NET page through your Hub the same way.
Once you have installed ASP.NET SignalR:
Install-Package Microsoft.AspNet.SignalR
You can create a startup class to configure SignalR:
[assembly: OwinStartup(typeof(AspNetQuartSignalR.Startup))]
namespace AspNetQuartSignalR
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
You have to reference a couple of scripts in your page:
jquery-2.1.1.js
jquery.signalR-2.1.1.js
and the automatically generated /signalr/hubs
Now you can create your own Hub:
public class QuartzHub : Hub
{
...
}
with methods which will allow you to interact with the scripts in your ASP.NET page.
Let's say your Hub has a method CheckQuartzStatus which gives you the status of all the quartz.net triggers configured:
public void CheckQuartzStatus()
{
string message = string.Empty;
var allTriggerKeys = Global.Scheduler.GetTriggerKeys(GroupMatcher<TriggerKey>.AnyGroup());
foreach (var triggerKey in allTriggerKeys)
{
ITrigger trigger = Global.Scheduler.GetTrigger(triggerKey);
message += string.Format("{0} = {1}", trigger.Key, Global.Scheduler.GetTriggerState(trigger.Key)) + Environment.NewLine;
}
Clients.All.onCheckQuartzStatus(message);
}
Your jQuery script can interact with this method in a very simple way:
quartz.server.checkQuartzStatus();
As you can see your Hub method at some point fires an action: onCheckQuartzStatus.
That is a call to an event defined in your javascript defined in the page :
quartz.client.onCheckQuartzStatus = function (message) {
alert(message);
};
You can see how the interaction works looking at the script in the Default.aspx page.
You can read a lot more here.
You're going to have to build all of this functionality yourself. Quartz.Net jobs run in the threadpool and you don't have a way of referencing them from the scheduler. You could do this by having the job write its progress somewhere and then have your timer check that spot for progress.
The sample here and documentation here seem to show how to do this with the JavaScript SignalR libray, I am trying on my own to figure this out using a console client application to GetAllStocks without any success.
Here is my client console app code just concentrating on the GetAllStocks not the update at this point :
using System;
using System.Collections;
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR.Client.Hubs;
namespace StockTicker.Client
{
class Program
{
static void Main(string[] args)
{
RunAsync().Wait();
}
private static async Task RunAsync()
{
var hubConnection = new HubConnection("http://localhost:8080/");
IHubProxy stockTickerMini= hubConnection.CreateHubProxy("stockTickerMini");
stockTickerMini.On("GetAllStocks", stocks =>
{
foreach (var stock in stocks)
{ Console.WriteLine(stock.Symbol + ":" + stock.Price); }
});
await hubConnection.Start();
}
}
}
The code you have is incorrect. GetAllStocks is a method that the client can invoke on the server (e.g. it's something the server exposes). You can do:
var stocks = await stockTickerMini.Invoke<IEnumerable<Stock>>("GetAllStocks");
If you want to get called back when stocks are being updated then you need to look at what the server side is calling back on the clients object:
Which is detailed right here:
http://www.asp.net/signalr/overview/hubs-api/hubs-api-guide-net-client#establishconnection