Unity Google Play Services - unity3d

I am trying to get Google play services into the game I have developed. Here is the script I have on my main screen. I get no response out of it at all. I have tried all the different SHA1 codes and I am not sure what is wrong. Any Ideas???
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GooglePlayGames;
using UnityEngine.UI;
using GooglePlayGames.BasicApi;
using UnityEngine.SocialPlatforms;
public class GPS_Main : MonoBehaviour {
private bool IsConnectedToGoogleServices;
public Text SignIn;
private void Awake()
{
PlayGamesClientConfiguration config = new PlayGamesClientConfiguration.Builder().Build();
PlayGamesPlatform.InitializeInstance(config);
PlayGamesPlatform.Activate();
}
// Use this for initialization
void Start () {
LogIn();
}
// Update is called once per frame
void Update () {
}
void LogIn()
{
Social.localUser.Authenticate(success => { });
}
public bool ConnectToGoogleServices()
{
if (!IsConnectedToGoogleServices)
{
Social.localUser.Authenticate((bool success) =>
{
IsConnectedToGoogleServices = success;
});
}
return IsConnectedToGoogleServices;
}
public static void ToAchievementUI()
{
if (Social.localUser.authenticated)
{
Social.ShowAchievementsUI();
}
else
{
Debug.Log("Not authenticated");
}
}
}
This has really been an annoying event. I have been through many videos and books trying to find the correct fix.

There are many things that cause this to happen, the best way to find it is to try connecting your phone and then using adb logcat to see what is causing the problem.
Also i have found a little bug in your function ConnectToGoogleServices :
public bool ConnectToGoogleServices()
{
if (!IsConnectedToGoogleServices)
{
Social.localUser.Authenticate((bool success) =>
{
IsConnectedToGoogleServices = success;
});
}
return IsConnectedToGoogleServices;
}
This function is always returning IsConnectedToGoogleServices initial state.

I tried a bit of explanation in this post Google Play Sign in for Unity
, however I can't understand from your question what are all options you have tried and where you are stuck in your problem. 6 months old question at the time of me writing this. Hope you've sorted this out already. If so, please post your findings here that may help others.
For anyone landing on this question for an answer, pls refer to my answer on the other post (link above) if that is of any help for your problem and also note down the problem in the code (on the question), I think AminSojoudi tried pointing it out as well. Social.localUser.Authenticate() is taking the argument of a callback function (refer documentation). So don't expect it to assign IsConnectedToGoogleServices the result (success or failure) within ConnectToGoogleServices() scope itself. If Authenticate() call runs faster than your code execution, you may get a success, but that won't happen and your function won't return the actual success status of Authenticate() function call anytime. If your rest of the code (leaderboard, achievements) relies on IsConnectedToGoogleServices Boolean flag, then those will not work as well.
public bool ConnectToGoogleServices()
{
if (!IsConnectedToGoogleServices)
{
Social.localUser.Authenticate((bool success) =>
{
IsConnectedToGoogleServices = success; // <-- callback result
});
}
return IsConnectedToGoogleServices; // <-- this won't return the result of a callback result.
}

Related

Post score not taking place but leaderboard UI shows

I am setting up a leaderboard service that i have implemented with the GooglePlayGames api. My authentication and showing the leaderboard works but my script for posting scores to the leaderboard does not work. I have been looking around for quite a while now and it seems like the syntax for posting score is always the same, which i have aswell.
void Start()
{
AuthenticateUser();
}
void AuthenticateUser()
{
PlayGamesClientConfiguration config = new PlayGamesClientConfiguration.Builder().Build();
PlayGamesPlatform.InitializeInstance(config);
PlayGamesPlatform.Activate();
Social.localUser.Authenticate((bool success) =>
{
if (success == true)
{
Debug.Log("Logged in to Google play");
}
else
{
Debug.Log("There was an error login in to Google Play");
}
});
}
public static void PostToLeaderboard(long newScore)
{
Social.ReportScore(10, GPGSIds.leaderboard_highscore, (bool success) =>
{
if (success == true)
{
Debug.Log("Score were sucessfully added to leaderboard");
}
else
{
Debug.Log("Unable to post score to leaderboard");
}
});
}
This is my code for authenticating and post score to the leaderboard. I have hard coded 10 in the code Social.ReportScore function call.
Any ideas on why this is? The leaderboardUI shows up but no scores.
Please make sure to run the method PostToLeaderboard(long newScore) to update your leaderboard before you call leaderboardUI method.
Here in this case you can try this.
puplic void leaderboardUI() {
PostToLeaderboard(long newScore);
// your code to show leaderboard
}

Facebook/Unity SDK, Web build login not working

I have tried changing the InteractiveConsole script that comes with the Facebook/Unity SDK to simply make it use Login via the facebook account, as a start. Before building for the web it works fine (inside Unity), I get the access token window and I can see my own facebook ID in the console afterwards. But when I build it for the web and click on the same login button nothing happens. I have no idea why.
Here's my code:
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public sealed class InteractiveConsole : MonoBehaviour
{
#region FB.Init() example
private void CallFBInit()
{
FB.Init(OnInitComplete, OnHideUnity);
}
private void OnInitComplete()
{
Debug.Log("FB.Init completed: Is user logged in? " + FB.IsLoggedIn);
CallFBLogin ();
}
private void OnHideUnity(bool isGameShown)
{
Debug.Log("Is game showing? " + isGameShown);
}
#endregion
#region FB.Login() example
private void CallFBLogin()
{
FB.Login("email,publish_actions", LoginCallback);
}
void LoginCallback(FBResult result)
{
if (!FB.IsLoggedIn)
{
Debug.Log ("User cancelled login.");
}
else
{
Debug.Log ("User ID: " + FB.UserId);
if(FB.IsLoggedIn)
Application.LoadLevel("main");
}
}
#endregion
void OnGUI()
{
if (Button("Login"))
{
CallFBInit();
}
}
private bool Button(string label)
{
return GUILayout.Button(
label
);
}
}
I'm sure I'm missing something. Can someone tell me what's wrong?
There's more I'd like to understand, is the Access Token Unity window there to replace the usual Login/Asking for Permissions window in the final game (as seen in basically every app used on facebook)? If not, how do I get the proper Login window?
I've the same problem, however I did find a way to make it work. If you directly link to the Unity Binary URL instead of linking to a secure Canvas page you should be able to login. However I don't know how to change the looks of the page around the unity3D application.

Correct way to call async methods from within a data-bound property setter?

Now I know properties do not support async/await for good reasons. But sometimes you need to kick off some additional background processing from a property setter - a good example is data binding in a MVVM scenario.
In my case, I have a property that is bound to the SelectedItem of a ListView. Of course I immediately set the new value to the backing field and the main work of the property is done. But the change of the selected item in the UI needs also to trigger a REST service call to get some new data based on the now selected item.
So I need to call an async method. I can't await it, obviously, but I also do not want to fire and forget the call as I could miss exceptions during the async processing.
Now my take is the following:
private Feed selectedFeed;
public Feed SelectedFeed
{
get
{
return this.selectedFeed;
}
set
{
if (this.selectedFeed != value)
{
this.selectedFeed = value;
RaisePropertyChanged();
Task task = GetFeedArticles(value.Id);
task.ContinueWith(t =>
{
if (t.Status != TaskStatus.RanToCompletion)
{
MessengerInstance.Send<string>("Error description", "DisplayErrorNotification");
}
});
}
}
}
Ok so besides the fact I could move out the handling from the setter to a synchronous method, is this the correct way to handle such a scenario? Is there a better, less cluttered solution I do not see?
Would be very interested to see some other takes on this problem. I'm a bit curious that I was not able to find any other discussions on this concrete topic as it seems very common to me in MVVM apps that make heavy use of databinding.
I have a NotifyTaskCompletion type in my AsyncEx library that is essentially an INotifyPropertyChanged wrapper for Task/Task<T>. AFAIK there is very little information currently available on async combined with MVVM, so let me know if you find any other approaches.
Anyway, the NotifyTaskCompletion approach works best if your tasks return their results. I.e., from your current code sample it looks like GetFeedArticles is setting data-bound properties as a side effect instead of returning the articles. If you make this return Task<T> instead, you can end up with code like this:
private Feed selectedFeed;
public Feed SelectedFeed
{
get
{
return this.selectedFeed;
}
set
{
if (this.selectedFeed == value)
return;
this.selectedFeed = value;
RaisePropertyChanged();
Articles = NotifyTaskCompletion.Create(GetFeedArticlesAsync(value.Id));
}
}
private INotifyTaskCompletion<List<Article>> articles;
public INotifyTaskCompletion<List<Article>> Articles
{
get { return this.articles; }
set
{
if (this.articles == value)
return;
this.articles = value;
RaisePropertyChanged();
}
}
private async Task<List<Article>> GetFeedArticlesAsync(int id)
{
...
}
Then your databinding can use Articles.Result to get to the resulting collection (which is null until GetFeedArticlesAsync completes). You can use NotifyTaskCompletion "out of the box" to data-bind to errors as well (e.g., Articles.ErrorMessage) and it has a few boolean convenience properties (IsSuccessfullyCompleted, IsFaulted) to handle visibility toggles.
Note that this will correctly handle operations completing out of order. Since Articles actually represents the asynchronous operation itself (instead of the results directly), it is updated immediately when a new operation is started. So you'll never see out-of-date results.
You don't have to use data binding for your error handling. You can make whatever semantics you want by modifying the GetFeedArticlesAsync; for example, to handle exceptions by passing them to your MessengerInstance:
private async Task<List<Article>> GetFeedArticlesAsync(int id)
{
try
{
...
}
catch (Exception ex)
{
MessengerInstance.Send<string>("Error description", "DisplayErrorNotification");
return null;
}
}
Similarly, there's no notion of automatic cancellation built-in, but again it's easy to add to GetFeedArticlesAsync:
private CancellationTokenSource getFeedArticlesCts;
private async Task<List<Article>> GetFeedArticlesAsync(int id)
{
if (getFeedArticlesCts != null)
getFeedArticlesCts.Cancel();
using (getFeedArticlesCts = new CancellationTokenSource())
{
...
}
}
This is an area of current development, so please do make improvements or API suggestions!
public class AsyncRunner
{
public static void Run(Task task, Action<Task> onError = null)
{
if (onError == null)
{
task.ContinueWith((task1, o) => { }, TaskContinuationOptions.OnlyOnFaulted);
}
else
{
task.ContinueWith(onError, TaskContinuationOptions.OnlyOnFaulted);
}
}
}
Usage within the property
private NavigationMenuItem _selectedMenuItem;
public NavigationMenuItem SelectedMenuItem
{
get { return _selectedMenuItem; }
set
{
_selectedMenuItem = val;
AsyncRunner.Run(NavigateToMenuAsync(_selectedMenuItem));
}
}
private async Task NavigateToMenuAsync(NavigationMenuItem newNavigationMenu)
{
//call async tasks...
}

not able to set focus on TextBox in a GWT app

This should not be causing me so much pain but it is. It is a very weird problem. In a GWT application, I have two .java files, login.java and application.java.
In login.java, I'm creating a user login page where if the username and password is verified the user is logged into the application and application.java takes from here.
Now in application. java's onModuleLoad() this is how i'm starting with a login page.
public void onModuleLoad() {
Login login = new Login();
login.textBoxUsername.setFocus(true);
RootLayoutPanel.get().add(login);}
This works great, except for the tiny problem of not being able to set focus on the username TextBox when the page loads. I have tried evrything I can think of. But the focus just doesn't get set on the TextBox. If anyone can suggest a solution, please do. Your help is greatly appreciated.
Solution: (In case it helps anyone facing the same issue)
final Login login = new Login();
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
public void execute () {
login.textBoxUsername.setFocus(true);
}
});
RootLayoutPanel.get().add(login);
Try using Scheduler.scheduleDeferred():
public void onModuleLoad() {
Login login = new Login();
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand () {
public void execute () {
login.textBoxUsername.setFocus(true);
}
});
RootLayoutPanel.get().add(login);
}
Update: answer updated to use Scheduler.get().scheduleDeferred() instead of DeferredCommand, which is deprecated.
Why using DefferedCommand, I think it's better to use someWidget.getElement().focus() which is a native Javascript. I'm using it everywhere, I've not seen any problem.
If your Widget extends Composite, you can:
#Override
protected void onAttach() {
super.onAttach();
textBoxUsername.setFocus(true);
}
It would be so easy for GWT to store a 'wantsFocus' in the internal state, and call focus after the widget is attached. We are still waiting after many years for that feature however...
Still, even after the attach handler is called, setFocus does not always work.
So in the meantime, our GwtUtil library has used the following code. It is a combination of several other solutions, and has been wrapped in a utility function:
static public void setFocus(final FocusWidget focusWidget) {
if (focusWidget.isAttached()) {
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
#Override
public void execute() {
focusWidget.setFocus(true);
}
});
} else {
focusWidget.addAttachHandler(new AttachEvent.Handler() {
#Override
public void onAttachOrDetach(AttachEvent event) {
if (event.isAttached()) {
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
#Override
public void execute() {
focusWidget.setFocus(true);
}
});
}
}
});
}
}
And call it like this:
setFocus(myTextBox);
It makes sense to use a utility function; If and when GWT finally makes setFocus work, you won't have to change your source code in multiple places.

Intermittent NSTimer problem in Release mode on device

I am having a problem where most, but not all, of the time on my device my NSTimer action is not being called when compiled in Release mode. It's always fine in Debug mode on the device, and it's always fine in either mode in the simulator.
The only thing that's slightly unusual about this situation is that it's wrapped with another class to allow us to inject platform-specific implementations of things like timers at runtime, thinking forwards to monodroid etc. Nothing particularly unusual going on though.
Code:
using System;
using MonoTouch.Foundation;
namespace OurCompany.PlatformAbstraction.Ios
{
public class IosTimer : IPlatformTimer
{
private NSTimer backingTimer;
public double IntervalMs{get; set;}
public IosTimer(double intervalMS)
{
this.IntervalMs = intervalMS;
}
public event EventHandler Elapsed;
private void NsTimerElapsed()
{
if (Elapsed != null)
{
Elapsed(this, EventArgs.Empty);
}
}
public void Start ()
{
TimeSpan ts = TimeSpan.FromMilliseconds(this.IntervalMs);
this.backingTimer = NSTimer.CreateRepeatingScheduledTimer(ts, NsTimerElapsed);
}
public void Stop ()
{
this.backingTimer.Invalidate();
this.backingTimer = null;
}
}
}
Calling code:
private IosTimer t;
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
t = new IosTimer(100);
t.Elapsed += UpdateLabel;
t.Start();
}
private void UpdateLabel(object sender, EventArgs e)
{
// not being called in Release mode on the phone
// works fine in Debug mode on the phone, works fine in both modes in the simulator
}
I'm also noticing general behaviour differences - where something works fine in the simulator but not on the device. Also slight behaviour changes given two identical deployments of the exact same code to the same device(!)
Posted this yesterday on the MonoTouch forums but it seems a bit quiet over there.
Thanks in advance.
Transpired this was threading related. Solved by using InvokeOnMainThread() in my Elapsed event handlers.