How to wait for PlayerPrefs.SetString to be saved on disk? - unity3d

In my recent published mobile game I have implemented an online leaderboard. Some users ran into issues on registration process. In short words the registration is coded like this:
// coroutine
DownloadLeaderBoard () {
if (string.IsNullOrEmpty (PlayerPrefs.GetString ("USERNAME"))) {
RegisterUser();
yield break;
}
// Download and display Leaderboard
}
// coroutine
RegisterUser () {
// user has entered a valid username
PlayerPrefs.SetString("USERNAME" username);
DownloadLeaderboard();
}
So after I saved the username, I have to make sure that it's on the disk before I call DownloadLeaderboard() again! How can I achieve that and prevent that RegisterUser() is called multiple times?

if (PlayerPrefs.HasKey("USERNAME")) {
// dont't register user again
}

Related

How to show Google play signin dialoge only once?

I'm using Google Play Games service in my unity game and want to silently login my game so that the dialogue popup at the top shows only once.
Right now everytime I open the game that dialogue comes up. like this
And it takes around 5s for the dialog thing to complete that's why I want to do it silently so that user can directly enter to game if they have just signed in.
I've seen in some games that when we opens the game for the very first time only then that dialogue comes and on next further opening the dialogue doesn't comes and we directly enter to the game.
My code is
void Start()
{
PlayGamesClientConfiguration config = new PlayGamesClientConfiguration.Builder()
.AddOauthScope("profile")
.RequestServerAuthCode(false)
.Build();
PlayGamesPlatform.InitializeInstance(config);
PlayGamesPlatform.DebugLogEnabled = true;
PlayGamesPlatform.Activate();
if (!PlayGamesPlatform.Instance.localUser.authenticated)
{
Debug.Log("We're not authenticated in, let's authenticate first");
PlayGamesPlatform.Instance.Authenticate(SignInInteractivity.CanPromptOnce,
(code) =>
{
if (code == SignInStatus.Success)
{
Debug.Log("We're not signed in, let's signin first");
/// Signed in! Hooray!
PlayFabClientAPI.LoginWithGoogleAccount(new LoginWithGoogleAccountRequest()
{
ServerAuthCode = PlayGamesPlatform.Instance.GetServerAuthCode(),
CreateAccount = true,
}, OnGoogleLoginSuccess, error =>
{
Debug.Log("Error " + code);
// TODO: Move to splash scene with practice mode only
});
}
else
{
/// Error signing in. We'll want to show a sign in button
}
}); /// <--- That "true" is very important!
}
else
{
Debug.Log("We're already signed in");
}
}
so the main issue is that PlayGamesPlatform.Instance.localUser.authenticated
always returns false.
Thanks!

How I can detect first app lauch in Flutter?

I work on a Flutter mobile app and I want to detect the first app launch to show a little tutorial to the user. I have tests the Shared-Preferences Module But when If I start the app for the first time The console tells me the key is not recognized, I think it's normal because this key does exist! There is another method for checking that?
Thank you guys
use shared preferences to store value that indicate if user has ever been in this page or not
like this
try {
final SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
splash = sharedPreferences.getString("SPLASH_DONE");
} catch (e) {
print("this is first time");
}
if (splash == null) {
page = AppSplashScreen();
} else {
page = LoginPage();
}
and after completing your first time operation call
sharedPreferences.setString("SPLASH_DONE", "DONE");

Ionic - flashes with wrong starting page on app start

Ive created 2 route guards... one which checks if the user is logged in and one if they are unauthenticated
When the app starts, very briefly it determines, while looking for the localstorage cookie, that the user doest exist and so shows the unauth page (i.e login page)
Im wondering what is the best approach to solve this - in my eyes the authguard with observale to see if the user is logged in or not was the best approach but there is that split second while the code runs that it cannot determine and it wants to show something.
Anyone have any similar issues/creative solutions to solve it.
I had this same issue a few months ago, and I solved it by creating an Auth Guard and returning a promise...
auth.guard.ts
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot,
): Observable<boolean> | Promise<boolean> | boolean {
return new Promise(resolve => {
const userAuthObs = this.afAuth.user.subscribe(user => {
if (user) {
resolve(true);
} else {
this.router.navigate(['signup']);
resolve(false);
}
});
});
}
The app just continues to load normally while it waits for this promise to decide where to direct the user.
You can watch a great video about creating auth guards here...
https://www.youtube.com/watch?v=RxLI9_ub6PM

button back to my app in the background and when you resume it starts again

I am developing an app in Xamarin.Forms, before I was trying to make a master detail page to become my MainPage when I logged in to my app, this I have already achieved. Now I have the problem that when I use the button behind the phone my app is miimiza and goes to the background which is the behavior I hope, but when I return to my app does not continue showing my master detail page, but returns to my LginPage.
It is as if my app was running twice or at least there were two instances of LoginPage existing at the same time, this is because in my LoginPage I trigger some DisplayAlert according to some messages that my page is listening through the MessaginCenter and they are they shoot twice.
Can someone tell me how I can return the same to my app on the master detail page and not restart in the strange way described?
LoginView.xaml.cs:
public partial class LogonView : ContentPage
{
LogonViewModel contexto = new LogonViewModel();
public LogonView ()
{
InitializeComponent ();
BindingContext = contexto;
MessagingCenter.Subscribe<LogonViewModel>(this, "ErrorCredentials", async (sender) =>
{
await DisplayAlert("Error", "Email or password is incorrect.", "Ok");
}
);
}
protected override void OnDisappearing()
{
base.OnDisappearing();
MessagingCenter.Unsubscribe<LogonViewModel>(this, "ErrorCredentials");
}
}
Part of my ViewModel:
if (Loged)
{
App.token = token;
Application.Current.MainPage = new RootView();
}
else
{
MessagingCenter.Send(this, "ErrorCredentials");
}
Thanks.
I hope this is in Android. All you can do is, you can override the backbuttonpressed method in MainActivity for not closing on back button pressed of the entry page. like below, you can add some conditions as well.
public override void OnBackPressed()
{
Page currentPage = Xamarin.Forms.Application.Current.MainPage.Navigation.NavigationStack.LastOrDefault();
if (currentPage != null)
{
if (currentPage.GetType().Name == "HomePage" || currentPage.GetType().Name == "LoginPage")
{
return;
}
}
base.OnBackPressed();
}
When you press the Home button, the application is paused and the
current state is saved, and finally the application is frozen in
whatever state it is. After this, when you start the app, it is
resumed from the last point it was saved with.
However, when you use the Back button, you keep traversing back in
the activity stack, closing one activity after another. in the end,
when you close the first activity that you opened, your application
exits. This is why whenever you close your application like this, it
gets restarted when you open it again.
Answer taken from this answer. The original question asks about the native Android platform, but it still applies here.
It means you have to Use Setting Plugin or save data in Application properties.
You have to add below code in App.xaml.cs file:
if (SettingClass.UserName == null)
MainPage = new LoginPage();
else
MainPage = new MasterDetailPage();
For Setting Plugin you can refer this link.

Titanium_iphone contacts

I am trying to list contacts with Titanium. WOrks on android device, but on iphone simulator doesn't return anything.
var contacts= Ti.Contacts.getAllPeople();
alert("contacts.length");
returns 0. I am not sure what am i missing here.
Make sure that you have contacts created on your iOS simulator:
Use Home button (CMD+Shift+H) to go to dashboard.
Open up Contacts app
Create few contacts which you want to retrieve in your app.
Also before you call Ti.Contacts.getAllPeople() you have to request authorisation to contact list. Try code below:
function processContacts() {
Ti.API.info('authorized');
var contacts = Ti.Contacts.getAllPeople();
Ti.API.info(contacts.length);
}
if (Ti.Contacts.contactsAuthorization == Ti.Contacts.AUTHORIZATION_AUTHORIZED){
processContacts();
} else if (Ti.Contacts.contactsAuthorization == Ti.Contacts.AUTHORIZATION_UNKNOWN){
Ti.Contacts.requestAuthorization(function(e){
if (e.success) {
processContacts();
} else {
Ti.API.info('disallowed');
}
});
} else {
Ti.API.info('disallowed');
}
One last thing, in your code you wrote: alert("contacts.length") which will always display dialog view with "contacts.length" as a string, not value. To call it properly you should write: alert(contacts.length) without double quotes.