Firebase/Unity Google Authentication Pop Up Missing - firebase

My code for Google Authentication works fine but the trouble is that once an email is selected, it does not display the pop-up again. It automatically selects the previous selected Gmail account even after signing out.
How do I always display the pop-up box for sign-in?
public void GoogleSignInClick()
{
configuration = new GoogleSignInConfiguration { WebClientId = GoogleWebAPI, RequestIdToken = true };
if (GoogleSignIn.Configuration == null)
{
GoogleSignIn.Configuration = configuration;
GoogleSignIn.Configuration.UseGameSignIn = false;
}
GoogleSignIn.Configuration.RequestIdToken = true;
GoogleSignIn.Configuration.RequestEmail = true;
GoogleSignIn.DefaultInstance.SignIn().ContinueWith(OnGoogleAuthenticatedFinished);
}

Related

How can I open Deeplink but not Open with Dialog in Xamarin Android

I am doing Deeplink in Xamarin. Everything works fine when I open the link like this:
private async void _viewmore_Tapped(object sender, EventArgs e)
{
string linkapp = "https://mydomain.me/ProductDetail/1";
await Browser.OpenAsync(linkapp, BrowserLaunchMode.SystemPreferred);
}
App.xaml.cs
protected override async void OnAppLinkRequestReceived(Uri uri)
{
if (uri.Host.ToLower() == "mydomain.me" && uri.Segments != null && uri.Segments.Length == 3)
{
string action = uri.Segments[1].Replace("/", "");
bool isActionParamsValid = int.TryParse(uri.Segments[2], out int productId);
if (action == "ProductDetail" && isActionParamsValid)
{
if (productId > 0)
{
var getProdID = await _apiService.LoadProductID(productId);
detailProduct = getProdID;
var detailContentPage = new ProductDetail(detailProduct);
detailContentPage.BindingContext = detailProduct;
await MainPage.Navigation.PushAsync(detailContentPage);
}
else
{
// it can be security attack => navigate to home page or login page.
App.Current.MainPage = new NavigationPage(new MainView(0));
}
}
}
base.OnAppLinkRequestReceived(uri);
}
MainActivity.cs
//Invite App Link
[IntentFilter(new[] { Android.Content.Intent.ActionView },
DataScheme = "https",
DataHost = "mydomain.me",
DataPathPrefix = "/",
AutoVerify = true,
Categories = new[] { Android.Content.Intent.CategoryDefault, Android.Content.Intent.CategoryBrowsable })]
[IntentFilter(new[] { Android.Content.Intent.ActionView },
DataScheme = "http",
DataHost = "mydomain.me",
AutoVerify = true,
DataPathPrefix = "/",
Categories = new[] { Android.Content.Intent.CategoryDefault, Android.Content.Intent.CategoryBrowsable })]
(For Android) Create a Digital Assets file named assetlinks.json
[
{
"relation":[
"delegate_permission/common.handle_all_urls"
],
"target":{
"namespace":"android_app",
"package_name":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"sha256_cert_fingerprints":[
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
]
}
}
]
I uploaded the link: https://mydomain.me/.well-known/assetlinks.json -> It's ok
When I execute: _viewmore_Tapped. It opens again Open with:
How can it not show the Open with dialog box, I want it to be able to automatically enter My App..
I know that the option: Always can be clicked, however I don't want that. Please note that when I select Open with My App it opens fine.
I've searched on google a lot, but I still haven't found a solution for it. Hoping for any help from everyone. Thank you
Update
Testing App-Links: https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site= https://mydomain.me:&relation=delegate_permission/common.handle_all_urls. And I found it to be fine

Save and load data to firebase not working unity

maybe my code will mess here beacuse I'm new into firebase stuff and there is lack doc for newbie like me, so I want to make save and load data from firebase, there is 2 scene the first for main menu and second one the main game,so when firstime login or auto login, user will load current user data from realtime database (I'm using firebase) also applies to user when back to main menu.
in the second scene itself, user load current user highscore data at first start then when game over if the score > lasthighscore that will save/update latest highscore to realtime database.
here the preview this is when I auto-login then playgame until game over:
it's supposed to be updated but not when back to main menu, I already try with player prefs since i erase all data when sign out so the highscore always be 0 and if login with other account that highscore is not belong to other account.
here my firebase script on main menu:
private void Start()
{
Time.timeScale = 1;
mainPanel.SetActive(true);
InitializeFirebase();
}
void InitializeFirebase()
{
auth = FirebaseAuth.DefaultInstance;
DBreference = FirebaseDatabase.DefaultInstance.RootReference;
auth.StateChanged += AuthStateChanged;
AuthStateChanged(this, null);
}
void AuthStateChanged(object sender, System.EventArgs eventArgs)
{
//This checks if the user (your local user) is the same as the one from the auth
if (auth.CurrentUser != User)
{
//this seems the same, but user could have been null before
bool signedIn = User != auth.CurrentUser && auth.CurrentUser != null;
if (!signedIn && User != null)
{
Debug.Log("Signed out " + User.UserId);
loginPanel.SetActive(true);
}
//this is important step, this user is the one you should be working with
User = auth.CurrentUser;
if (signedIn)
{
Debug.Log("Signed in " + User.UserId);
userNameShowText.text = User.DisplayName;
StartCoroutine(LoadUserData());
loginPanel.SetActive(false);
// //highScoreMainMenu.text = PlayerPrefs.GetInt("highscore").ToString("0000000");
}
else
{
loginPanel.SetActive(true);
}
}
}
public IEnumerator Login(string _email, string _password)
{
//Call the Firebase auth signin function passing the email and password
var LoginTask = auth.SignInWithEmailAndPasswordAsync(_email, _password);
//Wait until the task completes
yield return new WaitUntil(predicate: () => LoginTask.IsCompleted);
if (LoginTask.Exception != null)
{
//If there are errors handle them
Debug.LogWarning(message: $"Failed to register task with {LoginTask.Exception}");
FirebaseException firebaseEx = LoginTask.Exception.GetBaseException() as FirebaseException;
AuthError errorCode = (AuthError)firebaseEx.ErrorCode;
string message = "Login Failed!";
switch (errorCode)
{
case AuthError.MissingEmail:
message = "Missing Email";
break;
case AuthError.MissingPassword:
message = "Missing Password";
break;
case AuthError.WrongPassword:
message = "Wrong Password";
break;
case AuthError.InvalidEmail:
message = "Invalid Email";
break;
case AuthError.UserNotFound:
message = "Account does not exist";
break;
}
warningLoginText.text = message;
}
else
{
//User is now logged in
//Now get the result
User = LoginTask.Result;
Debug.LogFormat("User signed in successfully: {0} ({1})", User.DisplayName, User.Email);
warningLoginText.text = "";
confirmLoginText.text = "Logged In";
StartCoroutine(LoadUserData());
yield return new WaitForSeconds(2);
userNameShowText.text = User.DisplayName;
UserDataScreen(); // Change to user data UI
confirmLoginText.text = "";
ClearLoginFeilds();
ClearRegisterFeilds();
}
}
public IEnumerator UpdateHighScore(int _highScore)
{
var DBTask = DBreference.Child("users").Child(auth.CurrentUser.UserId).Child("highscore").SetValueAsync(_highScore);
yield return new WaitUntil(predicate: () => DBTask.IsCompleted);
if (DBTask.Exception != null)
{
Debug.LogWarning(message: $"Failed to register task with {DBTask.Exception}");
}
else
{
//giscrore now updated
}
}
and this is for the game scene also same function for update higscore like on main menu.
void Start()
{
InitializeFirebase();
YetGameOver();
//GetScore
score = 0;
scoreText.text = score.ToString("00000");
//highScoreText.text = "HI :" + PlayerPrefs.GetInt("highscore", 0).ToString("00000");
maxTime = .1f;
}
void InitializeFirebase()
{
auth = FirebaseAuth.DefaultInstance;
DBreference = FirebaseDatabase.DefaultInstance.RootReference;
auth.StateChanged += AuthStateChanged;
AuthStateChanged(this, null);
}
void AuthStateChanged(object sender, System.EventArgs eventArgs)
{
//This checks if the user (your local user) is the same as the one from the auth
if (auth.CurrentUser != User)
{
//this seems the same, but user could have been null before
bool signedIn = User != auth.CurrentUser && auth.CurrentUser != null;
if (!signedIn && User != null)
{
Debug.Log("Signed out " + User.UserId);
}
//this is important step, this user is the one you should be working with
User = auth.CurrentUser;
if (signedIn)
{
Debug.Log("Signed in " + User.UserId);
StartCoroutine(LoadUserData());
//highScoreMainMenu.text = PlayerPrefs.GetInt("highscore").ToString("0000000");
}
}
}
public void GameOver()
{
SaveData();
StartCoroutine(WaitToDeath());
}
public void SaveData()
{
Debug.Log("Saved");
StartCoroutine(UpdateHighScore(PlayerPrefs.GetInt("highscore", 0)));
}
public IEnumerator WaitToDeath()
{
_CamShake.instance.shouldShake = true;
DeathSound();
gameOverPanel.SetActive(true);
endHighScoreText.text = "HI :" + PlayerPrefs.GetInt("highscore").ToString("0000000");
scoreText.gameObject.SetActive(false);
highScoreText.gameObject.SetActive(false);
yield return new WaitForSeconds(.1f);
//_AdmobAds.instance.ShowInterstitialAd();
isStarted = false;
isGameOver = true;
Time.timeScale = 0;
}
//same function like main menu
public IEnumerator UpdateHighScore(int _highScore)
{
var DBTask = DBreference.Child("users").Child(auth.CurrentUser.UserId).Child("highscore").SetValueAsync(_highScore);
yield return new WaitUntil(predicate: () => DBTask.IsCompleted);
if (DBTask.Exception != null)
{
Debug.LogWarning(message: $"Failed to register task with {DBTask.Exception}");
}
else
{
//highscore are now updated
}
}
public IEnumerator LoadUserData()
{
//Get the currently logged in user data
var DBTask = DBreference.Child("users").Child(User.UserId).GetValueAsync();
yield return new WaitUntil(predicate: () => DBTask.IsCompleted);
if (DBTask.Exception != null)
{
Debug.LogWarning(message: $"Failed to register task with {DBTask.Exception}");
}
else if (DBTask.Result.Value == null)
{
//No data exists yet
highScoreText.text = "0";
endHighScoreText.text = "0";
}
else
{
//Data has been retrieved
DataSnapshot snapshot = DBTask.Result;
highScoreText.text = endHighScoreText.text = snapshot.Child("highscore").Value.ToString();
}
}
You don't capture child in this method. You can only capture all the data from the root. So, simply remove the child. It will work.
my solution to firebase realtime database not working was that my google-services.json wasnt updated after adding the google-services.json from firebase auth. firebase, project overview cogwheel, project settings, json on that page somewhere.
and my problem with firebase auth before that was that i didnt set the Client ID in unity, window, google play games, setup, android setup.. get the id from google play console, play games services, setup & management, configuration, and figure out how to add game server credentials

Firebase UI Email Link signin intent extra is null

The following 3 functions are used to set up email and other auth checks (called in order)
private void buildSignInIntentBuilder() {
ActionCodeSettings actionCodeSettings = ActionCodeSettings.newBuilder()
.setAndroidPackageName(getString(R.string.packageName), true, null)
.setHandleCodeInApp(true)
.setUrl(getString(R.string.dynamic_link_url))
.build();
List<AuthUI.IdpConfig> providers = Arrays.asList(
new AuthUI.IdpConfig.EmailBuilder()
.enableEmailLinkSignIn()
.setActionCodeSettings(actionCodeSettings)
.build(),
// new AuthUI.IdpConfig.EmailBuilder().setRequireName(false).build(),
new AuthUI.IdpConfig.PhoneBuilder()
.build(),
new AuthUI.IdpConfig.GoogleBuilder()
.build(),
new AuthUI.IdpConfig.FacebookBuilder()
.build());
signInIntentBuilder = AuthUI.getInstance()
.createSignInIntentBuilder()
.setIsSmartLockEnabled(false)
.setAvailableProviders(providers)
.setLogo(R.drawable.icon_forget_me_not_1);
}
private void catchEmailLinkSignIn() {
Log.d(TAG, "Intent: " + getIntent().getExtras());
if (AuthUI.canHandleIntent(getIntent())) {
if (getIntent().getExtras() == null) {
return;
}
String link = getIntent().getExtras().getString(ExtraConstants.EMAIL_LINK_SIGN_IN);
Log.d(TAG, "link: " + link);
if (link != null) {
signInIntentBuilder.setEmailLink(link);
}
}
}
private void createCheckAndSigninListener() {
// set firebase sign in listener
mAuthStateListner = firebaseAuth -> {
// Already logged in
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
Log.d(TAG, "user already signed in");
// Check user even if signed in to register him to database (if haven't)
FirebaseAuthHelper.getInstance().checkRegisterUser(user, this, CHECK_USER_DB);
} else {
Log.d(TAG, "user hasn't signed in");
// Signed out or hasn't logged in
startActivityForResult(
signInIntentBuilder
.build(),
RC_SIGN_IN
);
}
};
}
I have set up a dynamic link with firebase hosting. And being able to redirect into the same activity upon clicking the received email link.
However,
String link = getIntent().getExtras().getString(ExtraConstants.EMAIL_LINK_SIGN_IN);
Log.d(TAG, "link: " + link); // --> produces "link: null"
Shows despite successfully getting a intent, there is no EMAIL_LINK_SIGNIN extra in the getExtras(). I spend few hours looking into the source code of FirebaseUi, but I didn't find where the constant EMAIL_LINK_SIGN_IN is used and how is the intent from dynamic link parsed.
Any idea how to fix this problem is appreciated. I had already spent a whole day trying to figure this out.
Instead of using String link = getIntent().getExtras().getString(ExtraConstants.EMAIL_LINK_SIGN_IN);
use getIntent().getData().toString(); instead.

Set a job to failed using Hangfire with ASP.NET?

I have an ASP.NET app which sends emails whenever the user signs up in the web site. I'm using hangfire in order to manage the jobs and postal in order to send emails.
It all works great, but here's the thing:
I want the superuser to change how many times the APP can send the email before deleting the job.
Here's my code
public static void WelcomeUser(DBContexts.Notifications not)
{
try{
var viewsPath = Path.GetFullPath(HostingEnvironment.MapPath(#"~/Views/Emails"));
var engines = new ViewEngineCollection();
engines.Add(new FileSystemRazorViewEngine(viewsPath));
Postal.EmailService service = new Postal.EmailService(engines);
WelcomeUserMail welcomeUserMail = new WelcomeUserMail();
welcomeUserMail.To = not.ReceiverEmail;
welcomeUserMail.UserEmail = not.ReceiverEmail;
welcomeUserMail.From = BaseNotification.GetEmailFrom();
service.Send(welcomeUserMail);
}
catch(Exception e)
{
DBContexts.DBModel dbModel = new DBModel();
DBContexts.Notifications notificacionBD = dbModel.Notifications.Find(not.NotificationID);
notificacionBD.Status = false;
notificacionBD.Timestamp = DateTime.Now;
notificacionBD.Error = e.Message;
int numberOfRetriesAllowed = ParameterHelper.getNumberOfRetriesAllowed();
if (notificacionBD.Retries > numberOfRetriesAllowed)
{
//In this case Hangfire won't put this job in the failed section but rather in the processed section.
dbModel.SaveChanges();
}
else
{
notificacionBD.Retries++;
dbModel.SaveChanges();
throw new Exception(e.Message);
}
}
}
Why not just add attributes to handle it automatically?
[AutomaticRetry(Attempts = 10, LogEvents = true, OnAttemptsExceeded = AttemptsExceededAction.Delete)]
public void MyTask(){
//doing stuff
}
Or you could just make your own attribute that mimics the AutommaticRetryAttribute class but you handle it how you want?
https://github.com/HangfireIO/Hangfire/blob/a5761072f18ff4caa80910cda4652970cf52e693/src/Hangfire.Core/AutomaticRetryAttribute.cs

Caliburn.Micro Screen.CanClose() and MessageDialog().ShowAsync()

I'm currently using Caliburn.Micro 2.0 for my Windows Phone 8.1 project (Universal App) and I'm having problem with conditionally cancelling page close after user clicks a MessageDialog button.
It seems that Caliburn closes page after leaving CanClose() method, not waiting for the callback which is called after async MessageDialog.
public class MyViewModel: Screen
{
public override async void CanClose(Action<bool> callback)
{
MessageDialog dlg = new MessageDialog("Close?","Confirmation");
dlg.Commands.Add(new UICommand() { Id = 0, Label = "Yes" });
dlg.Commands.Add(new UICommand() { Id = 1, Label = "No" });
var result = await dlg.ShowAsync();
callback((int)result.Id == 0);
}
}
The only solution I have at the moment is set a field with a flag indicating if the page can be closed. On the user attempt to navigate back I tell Caliburn to abort the close and I display the confirmation dialog. When I get the result I set the flag to true and navigate back manually. This causes another call to CanClose, but this time I set the callback to true and skip the dialog part.
I don't like this solution much, but it is only way I managed to solve this problem.
private bool canClose = false;
public override async void CanClose(Action<bool> callback)
{
callback(canClose);
if (!canClose)
{
MessageDialog dlg = new MessageDialog("Close?","Confirmation");
dlg.Commands.Add(new UICommand() { Id = 0, Label = "Yes" });
dlg.Commands.Add(new UICommand() { Id = 1, Label = "No" });
var result = await dlg.ShowAsync();
if ((int)result.Id == 0)
{
canClose = true;
navigationService.GoBack();
}
}
}
PS: I don't use MessageDialog directly in my ViewModel, I'm using a dialog service interface for popups. I just used it here to demonstrate the issue.
While the enhancement CanClose isn't set, this is my approach utilize Navigating event to solve this 'problem'
If user could just GoBack() would be easy to handle, but in my case, there's many options to navigate. So, the only way that I found to solve it is described below:
public MyViewModel(INavigationService navigationService)
{
_navigationService = navigationService;
_navigationService.Navigating += OnGoBack;
}
private async void OnGoBack(object sender, NavigatingCancelEventArgs e)
{
e.Cancel = true;
var dlg = new MessageDialog("Close?", "Confirmation"); //Dialog for demo purpose only!
dlg.Commands.Add(new UICommand() { Id = 0, Label = "Yes" });
dlg.Commands.Add(new UICommand() { Id = 1, Label = "No" });
var result = await dlg.ShowAsync();
if ((int) result.Id != 0) return;
_navigationService.Navigating -= OnGoBack;
if (e.NavigationMode == NavigationMode.Back)
_navigationService.GoBack();
else
{
var myViewModel = Type.GetType($"YourNameSpaceViewModels.{e.SourcePageType.Name}Model");
_navigationService.NavigateToViewModel(myViewModel);
}
}
Explaination:
$"YourNameSpaceViewModels.{e.SourcePageType.Name}Model"
Here I get the full path to my class where user want to goto
And so, I navigate to it _navigationService.NavigateToViewModel(myViewModel);

Resources