Hello people im new with Unity and C#.
I have this script to create/login users and post in firebase database (with email and password).
I copied it from a youtube tutorial with a little few modifications
using System.Collections;
using System.Collections.Generic;
using FullSerializer;
using Proyecto26;
using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using Firebase.Auth;
public class PlayerScores : MonoBehaviour
{
public Text scoreText;
public InputField getScoreText;
public InputField emailText;
public InputField usernameText;
public InputField passwordText;
private System.Random random = new System.Random();
User user = new User();
private string databaseURL = "testingurl";
private string AuthKey = "testingapikey";
public static fsSerializer serializer = new fsSerializer();
public static int playerScore;
public static string playerName;
private string idToken;
public static string localId;
private string getLocalId;
private void Start()
{
playerScore = random.Next(0, 101);
scoreText.text = "Score: " + playerScore;
}
public void OnSubmit()
{
PostToDatabase();
Debug.Log("datos subidos a database");
}
public void OnGetScore()
{
GetLocalId();
}
private void UpdateScore()
{
scoreText.text = "Score: " + user.userScore;
}
private void PostToDatabase(bool emptyScore = false, string idTokenTemp = "")
{
if (idTokenTemp == "")
{
idTokenTemp = idToken;
}
User user = new User();
if (emptyScore)
{
user.userScore = 0;
}
RestClient.Put(databaseURL + "/" + localId + ".json?auth=" + idTokenTemp, user);
}
private void RetrieveFromDatabase()
{
RestClient.Get<User>(databaseURL + "/" + getLocalId + ".json?auth=" + idToken).Then(response =>
{
user = response;
UpdateScore();
});
}
public void SignUpUserButton()
{
SignUpUser(emailText.text, usernameText.text, passwordText.text);
}
public void SignInUserButton()
{
SignInUser(emailText.text, passwordText.text);
}
private void SignUpUser(string email, string username, string password)
{
string userData = "{\"email\":\"" + email + "\",\"password\":\"" + password + "\",\"returnSecureToken\":true}";
RestClient.Post<SignResponse>("https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=" + AuthKey, userData).Then(
response =>
{
string emailVerification = "{\"requestType\":\"VERIFY_EMAIL\",\"idToken\":\"" + response.idToken + "\"}";
RestClient.Post(
"https://www.googleapis.com/identitytoolkit/v3/relyingparty/getOobConfirmationCode?key=" + AuthKey,
emailVerification);
localId = response.localId;
playerName = username;
PostToDatabase(true, response.idToken);
Debug.Log("SingUp Correcto");
}).Catch(error =>
{
Debug.Log("falta email/password");
Debug.Log(error);
});
}
private void SignInUser(string email, string password)
{
string userData = "{\"email\":\"" + email + "\",\"password\":\"" + password + "\",\"returnSecureToken\":true}";
RestClient.Post<SignResponse>("https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=" + AuthKey, userData).Then(
response =>
{
string emailVerification = "{\"idToken\":\"" + response.idToken + "\"}";
RestClient.Post(
"https://www.googleapis.com/identitytoolkit/v3/relyingparty/getAccountInfo?key=" + AuthKey,
emailVerification).Then(
emailResponse =>
{
fsData emailVerificationData = fsJsonParser.Parse(emailResponse.Text);
EmailConfirmationInfo emailConfirmationInfo = new EmailConfirmationInfo();
serializer.TryDeserialize(emailVerificationData, ref emailConfirmationInfo).AssertSuccessWithoutWarnings();
if (emailConfirmationInfo.users[0].emailVerified)
{
idToken = response.idToken;
localId = response.localId;
GetUsername();
Debug.Log("Login Correcto");
SceneManager.LoadScene("SignInEdit"); //para logear correctamente solo necesita que el email y password sean correctos, el username no importa.
}
else
{
Debug.Log("You are stupid, you need to verify your email dumb");
}
});
}).Catch(error =>
{
Debug.Log(error);
});
}
private void GetUsername()
{
RestClient.Get<User>(databaseURL + "/" + localId + ".json?auth=" + idToken).Then(response =>
{
playerName = response.userName;
});
}
private void GetLocalId()
{
RestClient.Get(databaseURL + ".json?auth=" + idToken).Then(response =>
{
var username = getScoreText.text;
fsData userData = fsJsonParser.Parse(response.Text);
Dictionary<string, User> users = null;
serializer.TryDeserialize(userData, ref users);
foreach (var user in users.Values)
{
if (user.userName == username)
{
getLocalId = user.localId;
RetrieveFromDatabase();
break;
}
}
}).Catch(error =>
{
Debug.Log(error);
});
}
}
my problem is I cant save my firebase login between scenes, When I change scene I cant interact anymore with my firebase database.
I tried make a dontdestroyonload script and add a unity gameobject what is containing my PlayerScore script, but dont worked.
I readed im need to store my userid in a static variable to call it from anywhere but I dont know how because im prettly new with c# coding
Can someone give some guidance?, thanks.
PS: the script of above need another 3 script to works, where store/get some values.
If is necessary I add them.
I think that there might be some confusion here as I see a reference to the official Firebase Unity SDK mixed with raw REST calls in RestClient. I'll answer this assuming that you're ok with using the Unity SDK. This is a far simpler integration than attempting to manually use the Firebase SDK (and gets you nice benefits - such as local caching).
1) Firebase Authentication
Once Firebase Authentication is initialized, FirebaseAuth.DefaultInstance.CurrentUser will always contain your currently signed in user or null if the user is not signed in. This value is actually stored in C++ and accessed through C#, meaning that it doesn't actually know about or abide by Unity's typical object lifecycles. That means that once you've signed in a user, this value will always hold the current user without the need to persist it across scene boundaries. In fact, this value is even preserved across runs of your game (meaning that your players don't have to log in every time).
A warning about this though: CurrentUser is updated asynchronously -- that is that there is no real guarantee that CurrentUser is up to date -- so it's generally safe to register a StateChanged listener as Puf suggested from the documentation:
Firebase.Auth.FirebaseAuth auth;
Firebase.Auth.FirebaseUser user;
// Handle initialization of the necessary firebase modules:
void InitializeFirebase() {
Debug.Log("Setting up Firebase Auth");
auth = Firebase.Auth.FirebaseAuth.DefaultInstance;
auth.StateChanged += AuthStateChanged;
AuthStateChanged(this, null);
}
// Track state changes of the auth object.
void AuthStateChanged(object sender, System.EventArgs eventArgs) {
if (auth.CurrentUser != user) {
bool signedIn = user != auth.CurrentUser && auth.CurrentUser != null;
if (!signedIn && user != null) {
Debug.Log("Signed out " + user.UserId);
}
user = auth.CurrentUser;
if (signedIn) {
Debug.Log("Signed in " + user.UserId);
}
}
}
void OnDestroy() {
auth.StateChanged -= AuthStateChanged;
auth = null;
}
I would highly recommend watching my tutorial on Firebase Authentication to see how I think about integrating this with a game. The link you shared is appropriate, but I'm a little curious about the various REST calls I see in your code.
If you're using the Firebase Unity SDK, email/password authentication should be as easy as:
auth.CreateUserWithEmailAndPasswordAsync(email, password).ContinueWith(task => {
if (task.IsCanceled) {
Debug.LogError("CreateUserWithEmailAndPasswordAsync was canceled.");
return;
}
if (task.IsFaulted) {
Debug.LogError("CreateUserWithEmailAndPasswordAsync encountered an error: " + task.Exception);
return;
}
// Firebase user has been created.
Firebase.Auth.FirebaseUser newUser = task.Result;
Debug.LogFormat("Firebase user created successfully: {0} ({1})",
newUser.DisplayName, newUser.UserId);
});
to create a user and
auth.SignInWithEmailAndPasswordAsync(email, password).ContinueWith(task => {
if (task.IsCanceled) {
Debug.LogError("SignInWithEmailAndPasswordAsync was canceled.");
return;
}
if (task.IsFaulted) {
Debug.LogError("SignInWithEmailAndPasswordAsync encountered an error: " + task.Exception);
return;
}
Firebase.Auth.FirebaseUser newUser = task.Result;
Debug.LogFormat("User signed in successfully: {0} ({1})",
newUser.DisplayName, newUser.UserId);
});
to sign them in. That is, there should be no need to use RestClient.
2) Realtime Database
Once you're authenticated, any calls to the Firebase Realtime Database SDK will automatically use the CurrentUser value (as I mentioned before - it persists on the C++ side of the SDK).
If you're hoping to use rules to secure user data such as:
{
"rules": {
"users": {
"$user_id": {
// grants write access to the owner of this user account
// whose uid must exactly match the key ($user_id)
".write": "$user_id === auth.uid"
}
}
}
}
Then writing data:
Database.DefaultInstance.GetReference($"/users/{FirebaseAuth.DefaultInstance.CurrentUser.UserId}/mySecret").SetValueAsync("flowers");
should just work.
I hope that all helps!
--Patrick
The Firebase SDK automatically persists the authentication state, and tries to restore it automatically too. You'll just need to write code to pick it up, which involves attaching a listener to the auth state.
See the first snippet in the Firebase documentation on getting the currently signed in user:
The recommended way to get the current user is by setting a listener on the Auth object:
Firebase.Auth.FirebaseAuth auth;
Firebase.Auth.FirebaseUser user;
// Handle initialization of the necessary firebase modules:
void InitializeFirebase() {
Debug.Log("Setting up Firebase Auth");
auth = Firebase.Auth.FirebaseAuth.DefaultInstance;
auth.StateChanged += AuthStateChanged;
AuthStateChanged(this, null);
}
// Track state changes of the auth object.
void AuthStateChanged(object sender, System.EventArgs eventArgs) {
if (auth.CurrentUser != user) {
bool signedIn = user != auth.CurrentUser && auth.CurrentUser != null;
if (!signedIn && user != null) {
Debug.Log("Signed out " + user.UserId);
}
user = auth.CurrentUser;
if (signedIn) {
Debug.Log("Signed in " + user.UserId);
}
}
}
void OnDestroy() {
auth.StateChanged -= AuthStateChanged;
auth = null;
}
Related
I am creating a program that uses Firebase Google auth to SignIn/SignUp in c#. And Firestore as a database. I need to save the data of new users who signup. But I don't know how to differentiate new user who signs up and old user who sign in using google auth.
How to find this
Nothing i tried works.
private void OnSignIn()
{
GoogleSignIn.Configuration = configuration;
GoogleSignIn.Configuration.UseGameSignIn = false;
GoogleSignIn.Configuration.RequestIdToken = true;
AddToInformation("Calling SignIn");
GoogleSignIn.DefaultInstance.SignIn().ContinueWith(OnAuthenticationFinished);
}
internal void OnAuthenticationFinished(Task<GoogleSignInUser> task)
{
if (task.IsFaulted)
{
using (IEnumerator<Exception> enumerator = task.Exception.InnerExceptions.GetEnumerator())
{
if (enumerator.MoveNext())
{
GoogleSignIn.SignInException error = (GoogleSignIn.SignInException)enumerator.Current;
AddToInformation("Got Error: " + error.Status + " " + error.Message);
}
else
{
AddToInformation("Got Unexpected Exception?!?" + task.Exception);
}
}
}
else if (task.IsCanceled)
{
AddToInformation("Canceled");
}
else
{
AddToInformation("Welcome: " + task.Result.DisplayName + "!");
// AddToInformation("User Status: "+ task.Result.)
AddToInformation("Email = " + task.Result.Email);
AddToInformation("Google ID Token = " + task.Result.IdToken);
AddToInformation("Email = " + task.Result.Email);
SignInWithGoogleOnFirebase(task.Result.IdToken);
}
}
private void SignInWithGoogleOnFirebase(string idToken)
{
Credential credential = GoogleAuthProvider.GetCredential(idToken, null);
auth.SignInWithCredentialAsync(credential).ContinueWith(task =>
{
AggregateException ex = task.Exception;
if (ex != null)
{
if (ex.InnerExceptions[0] is FirebaseException inner && (inner.ErrorCode != 0))
AddToInformation("\nError code = " + inner.ErrorCode + " Message = " + inner.Message);
}
else
{
AddToInformation("Sign In Successful.");
}
});
}
When SignInWithCredentialAsync completes, you get back a FirebaseUser object. This object has Metadata property with two values: CreationTimestamp and LastSignInTimestamp. If those values are the same or really close to each other, the user was just created.
I have a class created through a few different sources to connect, stay connected, read, and interact with a selected Twitch channel, but there seems to be no information as to how to do certain things.
One of the issues is that the names of the chatters are always in all lowercase characters.
The other issue is that there doesnt seem to be any information of users. Ie are they a mod, subscriber, VIP?
While the roles parts arent that high priority for me, I want for the names to be properly capitalized.
Is there any trick that can do this?
using System;
using System.IO;
using System.Net.Sockets;
using UnityEngine;
public class TwitchConnect : MonoBehaviour
{
public static TwitchConnect instance;
public TwitchAccountData TwitchSettings = new();
public event Action<string, string> OnChatMessage;
public event Action<string> OnLoggedIn;
public event Action OnLoggedOut;
public event Action<string> OnInvalidLogin;
public bool loggedIn = false;
private TcpClient Twitch;
private StreamReader Reader;
private StreamWriter Writer;
//private const string URL = "irc.chat.twitch.tv";
private const string URL = "irc.twitch.tv";
private const int PORT = 6667;
private float PingCounter = 0;
private string saveTwitchPath = "twitchauth.json";
private void Awake()
{
DontDestroyOnLoad(gameObject);
instance = this;
saveTwitchPath = Application.persistentDataPath + "/twitchauth.json";
LoadAccount();
}
public void UpdateAccount(string nUser, string nOAuth, string nChannel)
{
TwitchSettings.User = nUser;
TwitchSettings.OAuth = nOAuth;
TwitchSettings.Channel = nChannel;
}
public void ConnectToTwitch()
{
DisconnectFromTwitch();
Twitch = new TcpClient(URL, PORT);
Reader = new StreamReader(Twitch.GetStream());
Writer = new StreamWriter(Twitch.GetStream());
TwitchSettings.User = TwitchSettings.User.ToLower();
TwitchSettings.Channel = TwitchSettings.Channel.ToLower();
Writer.WriteLine("PASS " + TwitchSettings.OAuth);
Writer.WriteLine("NICK " + TwitchSettings.User);
Writer.WriteLine($"USER {TwitchSettings.User} 8 * :{TwitchSettings.User}");
Writer.WriteLine("JOIN #" + TwitchSettings.Channel);
Writer.Flush();//initiate connection
}
public void DisconnectFromTwitch()
{
loggedIn = false;
PingCounter = 0;
Twitch?.Dispose();
Reader?.Dispose();
Writer?.Dispose();
Twitch = null;
Reader = null;
Writer = null;
OnLoggedOut?.Invoke();
}
public void SaveAccount()
{
string jsonTwitch = JsonUtility.ToJson(TwitchSettings, true);
File.WriteAllText(saveTwitchPath, jsonTwitch, System.Text.Encoding.Unicode);
Debug.LogWarning("Twitch account settings saved!");
}
public void LoadAccount()
{
//twitch saved account settings - user, oauth, channel
if (File.Exists(saveTwitchPath))
{
string jsonSettings = File.ReadAllText(saveTwitchPath, System.Text.Encoding.Unicode);
JsonUtility.FromJsonOverwrite(jsonSettings, TwitchSettings);
Debug.LogWarning("Twitch account loaded, logging in...");
ConnectToTwitch();
}
}
public void SendIrcMessage(string message)
{
Writer.WriteLine(message);
Writer.Flush();
}
public void SendChatMessage(string message)
{
Writer.WriteLine($":{TwitchSettings.User}!{TwitchSettings.User}#{TwitchSettings.User}.tmi.twitch.tv PRIVMSG #{TwitchSettings.Channel} :{message}");
Writer.Flush();
}
private void Update()
{
if (Twitch == null) return;
if (!Twitch.Connected && loggedIn)
{
ConnectToTwitch();
}
PingCounter += Time.deltaTime;
if (PingCounter > 50)
{
Writer.WriteLine("PING " + URL);
Writer.Flush();
PingCounter = 0;
}
if (Twitch.Available > 0)
{
string message = Reader.ReadLine();
#if UNITY_EDITOR
Debug.Log(message);//DEBUG
#endif
if (message.Contains("PRIVMSG"))
{
int splitPoint = message.IndexOf("!");
string chatter = message[1..splitPoint];//get chatter name
splitPoint = message.IndexOf(":", 1);
string msg = message[(splitPoint + 1)..];//get message only
OnChatMessage?.Invoke(chatter, msg);
}
else if (message.Contains(":Welcome, GLHF!"))//successful login
{
SaveAccount();
loggedIn = true;
OnLoggedIn?.Invoke(TwitchSettings.User);
}
else if (message.Contains(":Invalid NICK"))
{
OnInvalidLogin?.Invoke("Invalid NICK");
}
else if (message.Contains(":Improperly formatted auth"))
{
OnInvalidLogin?.Invoke("Improperly formatted auth");
}
}
}
private void OnDestroy()
{
DisconnectFromTwitch();
}
}
For TMI - Twitch Messaging Interface to get DisplayName and Role information you need to enable some IRCv3 capabilities then updates your parser to extract the data.
Before PASS you should send
CAP REQ :twitch.tv/commands twitch.tv/tags
So,
Writer.WriteLine("PASS " + TwitchSettings.OAuth);
becomes
Writer.WriteLine("CAP REQ :twitch.tv/commands twitch.tv/tags");
Writer.WriteLine("PASS " + TwitchSettings.OAuth);
To enable additional data - https://dev.twitch.tv/docs/irc/capabilities
This will then add additioanl data to PRIVMSGs sent by Twitch.
These are commonly referered to as IRCv3 Tags.
This is an example from the documentations
#badge-info=;badges=broadcaster/1;client-nonce=28e05b1c83f1e916ca1710c44b014515;color=#0000FF;display-name=foofoo;emotes=62835:0-10;first-msg=0;flags=;id=f80a19d6-e35a-4273-82d0-cd87f614e767;mod=0;room-id=713936733;subscriber=0;tmi-sent-ts=1642696567751;turbo=0;user-id=713936733;user-type= :foofoo!foofoo#foofoo.tmi.twitch.tv PRIVMSG #bar :bleedPurple
https://dev.twitch.tv/docs/irc/send-receive-messages#receiving-chat-messages
This user:
sent the message bleedpurple in the channel bar
has the display-name of foofoo this will be the Capitislation of the user if any is set by the user
has the badges of broadcaster (version 1 of said badge)
So for VIP or moderator you would monitor for the badges of vip or moderator and so on for whatever roles you are looking for.
Further reading is on https://dev.twitch.tv/docs/irc/tags#privmsg-tags
Some badge examples:
Comma-separated list of chat badges in the form, <badge>/<version>. For example, admin/1. There are many possible badge values, but here are few:
admin
bits
broadcaster
moderator
subscriber
staff
turbo
You would normally poke the badges API (channel or global) for available badges nad versions of those badges.
But the salient role based badges are in this non exhuastive list.
Hi I've looked through a lot of S.O. pages on this subject but mine is a little different. This has nothing to do with an anti-forgery protected login page or users hitting the back button. At our university we use University of Michigan's CoSign as a single-sign-on solution. Users are authenticated through cosign and on success the username is provided by the IIS server in Request.ServerVariables["REMOTE_USER"] and can then be used for authorization, etc.
Here's some code: in global.asax.cs:
Session["username"] = Request.ServerVariables["REMOTE_USER"];
On each page that might use Ajax (in a file Init.js; code from https://blog.alexmaccaw.com/jswebapps-csrf):
$(document).ready(function () {
SetCSRFHeader();
}
function SetCSRFHeader() {
var CSRF_HEADER = 'RequestVerificationToken';
var setCSRFToken = function (securityToken) {
jQuery.ajaxPrefilter(function (options, _, xhr) {
if (!xhr.crossDomain)
xhr.setRequestHeader(CSRF_HEADER, securityToken);
});
};
var theTokenVal = $('#__bothTokens').val();
setCSRFToken(theTokenVal);
}
In _Layout.cshtml:
#Html.AntiForgeryToken()
#{
string cookieToken, formToken, bothTokens;
AntiForgery.GetTokens(null, out cookieToken, out formToken);
bothTokens = cookieToken + ":" + formToken;
}
<input type="hidden" id="__bothTokens" value="#(bothTokens)" />
I also wrote a class that implements IHttpModule to check all POST requests for the included header, parse it and validate it (code from https://security.stackexchange.com/questions/91164/how-to-check-the-origin-header-server-wide-in-iis-to-prevent-csrf):
public class HeaderCheck : IHttpModule
{
public HeaderCheck()
{
}
public void Init(HttpApplication application)
{
application.BeginRequest +=
(new EventHandler(this.Application_BeginRequest));
}
private void Application_BeginRequest(Object source,
EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
int errCode = 0;
int STATCODE = 403;
string cookieToken = "";
string formToken = "";
if (context.Request.HttpMethod == "POST") // only on POST requests
{
if (context.Request.Headers["Content-Type"] != null)
{
if (context.Request.Headers["Content-Type"] == "application/json;") // JSON check
{
if (context.Request.Headers["RequestVerificationToken"] != null)
{
string tokenHeaders = context.Request.Headers["RequestVerificationToken"];
string[] tokens = tokenHeaders.Split(':');
if (tokens.Length == 2)
{
cookieToken = tokens[0].Trim();
formToken = tokens[1].Trim();
}
}
else
{
errCode = 3;
}
}
else if (context.Request.Headers["Content-Type"].Length >= 19)
{
if (context.Request.Headers["Content-Type"].Substring(0, 19) == "multipart/form-data") // Form check
{
HttpCookie cookie = new HttpCookie("__RequestVerificationToken");
cookie = context.Request.Cookies["__RequestVerificationToken"];
formToken = context.Request.Form["__RequestVerificationToken"];
if (formToken == null) { tokenstr = "form null"; }
if (cookie != null)
{
cookieToken = cookie.Value;
System.Web.Helpers.AntiForgery.Validate(cookieToken, formToken);
}
else // cookie is null
{
errCode = 4;
}
}
}
else // neither acceptable content form
{
errCode = 5;
}
}
else // content type should not be null
{
errCode = 6;
}
if (errCode > 0)
{
try
{
System.Web.Helpers.AntiForgery.Validate(cookieToken, formToken);
}
catch (HttpAntiForgeryException e2)
{
string err = #"Antiforgery tokens not validated" +
"<br><b>Error in: </b>"
+ context.Request.Url.ToString()
+ "<br><b>Error Message: </b>"
+ e2.Message.ToString()
+ "<br><b>Stack Trace:</b><br>"
+ e2.StackTrace.ToString();
EmailContext.sendEmailOnError(err); // sends email to me for debugging
}
}
if (errCode > 0)
{
context.Response.StatusCode = STATCODE;
context.Response.Flush();
context.Response.End();
}
}
}
public void Dispose() { }
}
}
My questions: Why am I getting the error in the title of this question? How does AntiForgeryValidate know that the token was meant for me but somehow the token that's generated is for current user ""? Is there any way I can put the user into the token? I've even tried the advice at Reload AntiForgeryToken after a login to always regenerate the token the first time the user hits the home page (since they're already logged in at that point. Does this have anything to do with developing in visual studio in HTTP but the acceptance environment which is cosign-protected is https? Does it have anything to do with the fact that IIS is configured for Anonymous Authentication? (I think it needs to be to run under cosign).
Thanks for any advice.
EDIT: More and more I think this is due to IIS Anonymous Authentication being the only mode that's enabled. But any other mode requires some sort of second login, and since cosign is THE authentication provider, that doesn't help. So if anyone has any idea how to programmatically insert the user credentials received from cosign into IIS that might be the way forward.
I have a notification hub, and it, have a hub-namespace and it is almost full.
I'll create another hub, how do I programmatically know (Android), which one should I enter the user?
Android source code:
public class NotificationSettings {
public static String SenderId = "MyFirebaseSenderId";
public static String HubName = "myhub-hub";
public static String HubListenConnectionString = "Endpoint=sb://myapp.serv.../;SharedAccessKeyName=D..ure;SharedAccessKey=K..t/n8I/X..=";
}
RegistrationIntent:
public class RegistrationIntentService extends IntentService {
private static final String TAG = "RegIntentService";
private NotificationHub hub;
public RegistrationIntentService() {
super(TAG);
}
public ApplicationUtils getApplicationUtils() {
return (ApplicationUtils) getApplication();
}
#Override
protected void onHandleIntent(Intent intent) {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
String resultString = null;
String regID = null;
String storedToken = null;
String tag = null;
try {
tag ="_UserId:" + getApplicationUtils().getUsuario().Id;
} catch (Exception e){
return;
}
try {
if(FirebaseInstanceId.getInstance() == null){
FirebaseApp.initializeApp(this);
}
String FCM_token = FirebaseInstanceId.getInstance().getToken();
SaveSharedPreferences.setFCM(getApplicationContext(),FCM_token);
Log.d(TAG, "FCM Registration Token: " + FCM_token);
// Storing the registration id that indicates whether the generated token has been
// sent to your server. If it is not stored, send the token to your server,
// otherwise your server should have already received the token.
if (((regID=sharedPreferences.getString("registrationID", null)) == null)){
NotificationHub hub = new NotificationHub(NotificationSettings.HubName,
NotificationSettings.HubListenConnectionString, this);
Log.d(TAG, "Attempting a new registration with NH using FCM token : " + FCM_token);
regID = hub.register(FCM_token, tag).getRegistrationId();
// If you want to use tags...
// Refer to : https://azure.microsoft.com/en-us/documentation/articles/notification-hubs-routing-tag-expressions/
// regID = hub.register(token, "tag1,tag2").getRegistrationId();
resultString = "New NH Registration Successfully - RegId : " + regID;
Log.d(TAG, resultString);
sharedPreferences.edit().putString("registrationID", regID ).apply();
sharedPreferences.edit().putString("FCMtoken", FCM_token ).apply();
}
// Check if the token may have been compromised and needs refreshing.
else if (!((storedToken=sharedPreferences.getString("FCMtoken", "")).equals(FCM_token))) {
NotificationHub hub = new NotificationHub(NotificationSettings.HubName,
NotificationSettings.HubListenConnectionString, this);
Log.d(TAG, "NH Registration refreshing with token : " + FCM_token);
regID = hub.register(FCM_token, tag).getRegistrationId();
// If you want to use tags...
// Refer to : https://azure.microsoft.com/en-us/documentation/articles/notification-hubs-routing-tag-expressions/
// regID = hub.register(token, "tag1,tag2").getRegistrationId();
resultString = "New NH Registration Successfully - RegId : " + regID;
Log.d(TAG, resultString);
sharedPreferences.edit().putString("registrationID", regID ).apply();
sharedPreferences.edit().putString("FCMtoken", FCM_token ).apply();
}
else {
resultString = "Previously Registered Successfully - RegId : " + regID;
}
} .............................................
Now, it follows my downend code below, I do not know if it would be important in this case. But, it is developed in C # .Net:
public static async void sendPushNotification(ApiController controller, DataObjects.Notification notification)
{
// Get the settings for the server project.
HttpConfiguration config = controller.Configuration;
MobileAppSettingsDictionary settings =
controller.Configuration.GetMobileAppSettingsProvider().GetMobileAppSettings();
// Get the Notification Hubs credentials for the Mobile App.
string notificationHubName = settings.NotificationHubName;
string notificationHubConnection = settings
.Connections[MobileAppSettingsKeys.NotificationHubConnectionString].ConnectionString;
// Create a new Notification Hub client.
NotificationHubClient hub = NotificationHubClient.CreateClientFromConnectionString(notificationHubConnection, notificationHubName);
// Android payload
JObject data = new JObject();
data.Add("Id", notification.Id);
data.Add("Descricao", notification.Descricao);
...
//alteração com a colocação da tag priority em caso de erro teste sem
var androidNotificationPayload = "{ \"data\" : {\"message\":" + JsonConvert.SerializeObject(data) + "}}";
try
{
// Send the push notification and log the results.
String tag = "_UserId:"+notification.Id_usuario;
//var result = await hub.SendGcmNativeNotificationAsync(androidNotificationPayload);
var result = await hub.SendGcmNativeNotificationAsync(androidNotificationPayload, tag);
// Write the success result to the logs.
config.Services.GetTraceWriter().Info(result.State.ToString());
}
catch (System.Exception ex)
{
// Write the failure result to the logs.
config.Services.GetTraceWriter().Error(ex.Message, null, "Push.SendAsync Error");
}
}
I need a lot of help on this issue.
Thank you so much for this.
According to your description, I suggest you could write a api method which will insert new user to the notification hub(not on the client side) after checking the registrations is full or not.
We could use NotificationHubClient.GetAllRegistrationsAsync Method to get all AllRegistrations to local. Then we could count its number.
After checking successfully, then we will check enter user to which hub.
The workflow is:
New user registered:
Client: Send the user information to server web api method
Server: Check the notification hub is full(By calling NotificationHubClient.GetAllRegistrationsAsync or directly registered user if it failed registered into new hub)
Besides, notification hub provides different pricing tier.
I suggest you could consider scaling up your pricing tier to support multiple active devices.
I have a game completely in JavaScript. It sucks because I have to alter my C# plugins by shoving them into my plugin folder, and activate the commands inside the C# script using JavaScript.
I have downloaded "Let's Tweet in Unity" from the Asset store, and it comes with 2 Scripts. One script Defines "Twitter" and all the functions it can represent. The other is "Demo" which basically activates the functions within the Twitter Class.
So I altered "Demo" to my liking. But in this "Demo" it seems to want me to go through this process of Requesting a Token from twitter, which takes me to their website which gives me a Pin Number, then I have to go back to my app, paste the pin number, then write whatever I want to write, and only then I can post it.
I was wondering what methods I need to take to change this to that one method that just allows "such and such app" to have authentication to your Twitter account.
Currently the only commands I have are
GetRequestToken
GetAccessToken
PostToTwitter
And here is the script below:
using Twitter;
using UnityEngine;
public class TwitterTrigger : MonoBehaviour
{
// You need to register your game or application in Twitter to get cosumer key and secret.
// Go to this page for registration: http://dev.twitter.com/apps/new
public string CONSUMER_KEY;
public string CONSUMER_SECRET;
// You need to save access token and secret for later use.
// You can keep using them whenever you need to access the user's Twitter account.
// They will be always valid until the user revokes the access to your application.
const string PLAYER_PREFS_TWITTER_USER_ID = "TwitterUserID";
const string PLAYER_PREFS_TWITTER_USER_SCREEN_NAME = "TwitterUserScreenName";
const string PLAYER_PREFS_TWITTER_USER_TOKEN = "TwitterUserToken";
const string PLAYER_PREFS_TWITTER_USER_TOKEN_SECRET = "TwitterUserTokenSecret";
Twitter.RequestTokenResponse m_RequestTokenResponse;
Twitter.AccessTokenResponse m_AccessTokenResponse;
string m_PIN = "Please enter your PIN here.";
string m_Tweet = "Please enter your tweet here.";
// Use this for initialization
private void Start()
{
LoadTwitterUserInfo();
}
// Update is called once per frame
private void Update()
{
}
public void Post() {
/*post
StartCoroutine(API.PostTweet("This is a twitter api test.",
CONSUMER_KEY,
CONSUMER_SECRET,
m_AccessTokenResponse,
OnPostTweet));
*/
StartCoroutine(Twitter.API.PostTweet("This is a twitter api test.",
CONSUMER_KEY,
CONSUMER_SECRET,
m_AccessTokenResponse,
new Twitter.PostTweetCallback(this.OnPostTweet)));
}
public void GetAccessToken() {
StartCoroutine(Twitter.API.GetAccessToken(CONSUMER_KEY, CONSUMER_SECRET, m_RequestTokenResponse.Token, m_PIN,
new Twitter.AccessTokenCallback(this.OnAccessTokenCallback)));
}
public void GetRequestToken() {
StartCoroutine(Twitter.API.GetRequestToken(CONSUMER_KEY, CONSUMER_SECRET,
new Twitter.RequestTokenCallback(this.OnRequestTokenCallback)));
}
private void LoadTwitterUserInfo()
{
m_AccessTokenResponse = new AccessTokenResponse();
m_AccessTokenResponse.UserId = PlayerPrefs.GetString(PLAYER_PREFS_TWITTER_USER_ID);
m_AccessTokenResponse.ScreenName = PlayerPrefs.GetString(PLAYER_PREFS_TWITTER_USER_SCREEN_NAME);
m_AccessTokenResponse.Token = PlayerPrefs.GetString(PLAYER_PREFS_TWITTER_USER_TOKEN);
m_AccessTokenResponse.TokenSecret = PlayerPrefs.GetString(PLAYER_PREFS_TWITTER_USER_TOKEN_SECRET);
if (!string.IsNullOrEmpty(m_AccessTokenResponse.Token) &&
!string.IsNullOrEmpty(m_AccessTokenResponse.ScreenName) &&
!string.IsNullOrEmpty(m_AccessTokenResponse.Token) &&
!string.IsNullOrEmpty(m_AccessTokenResponse.TokenSecret))
{
string log = "LoadTwitterUserInfo - succeeded";
log += "\n UserId : " + m_AccessTokenResponse.UserId;
log += "\n ScreenName : " + m_AccessTokenResponse.ScreenName;
log += "\n Token : " + m_AccessTokenResponse.Token;
log += "\n TokenSecret : " + m_AccessTokenResponse.TokenSecret;
Debug.Log(log);
}
}
private void OnRequestTokenCallback(bool success, RequestTokenResponse response)
{
if (success)
{
string log = "OnRequestTokenCallback - succeeded";
log += "\n Token : " + response.Token;
log += "\n TokenSecret : " + response.TokenSecret;
print(log);
m_RequestTokenResponse = response;
//API.OpenAuthorizationPage(response.Token);
//GetAccessToken();
//Post();
}
else
{
print("OnRequestTokenCallback - failed.");
}
}
private void OnAccessTokenCallback(bool success, AccessTokenResponse response)
{
if (success)
{
string log = "OnAccessTokenCallback - succeeded";
log += "\n UserId : " + response.UserId;
log += "\n ScreenName : " + response.ScreenName;
log += "\n Token : " + response.Token;
log += "\n TokenSecret : " + response.TokenSecret;
print(log);
m_AccessTokenResponse = response;
PlayerPrefs.SetString(PLAYER_PREFS_TWITTER_USER_ID, response.UserId);
PlayerPrefs.SetString(PLAYER_PREFS_TWITTER_USER_SCREEN_NAME, response.ScreenName);
PlayerPrefs.SetString(PLAYER_PREFS_TWITTER_USER_TOKEN, response.Token);
PlayerPrefs.SetString(PLAYER_PREFS_TWITTER_USER_TOKEN_SECRET, response.TokenSecret);
//Post();
}
else
{
print("OnAccessTokenCallback - failed.");
}
}
private void OnPostTweet(bool success)
{
print("OnPostTweet - " + (success ? "succedded." : "failed."));
}
}