Is there a more sane way to program the following super simple set/get/close test program? Note that I had to duplicate the Redis close code and include it in both the set error path and in the get complete path.
import io.vertx.core.Vertx;
import io.vertx.redis.RedisClient;
import io.vertx.redis.RedisOptions;
public class RedisTest {
public static void main(String[] args) throws Exception {
Vertx vertx = Vertx.vertx();
String host = "localhost";
final RedisClient client = RedisClient.create(vertx,
new RedisOptions().setHost(host));
client.set("key", "value", r -> {
if (r.succeeded()) {
System.out.println("key stored");
client.get("key", s -> {
if (s.succeeded()) {
System.out.println("Retrieved value: " + s.result());
} else {
System.out.println("Connection or Operation Failed " + s.cause());
}
System.out.println("Closing Redis connection");
client.close(t -> {
if (s.succeeded()) {
System.out.println("Redis closed successfully.");
} else {
System.out.println("Connection or Operation Failed " + t.cause());
}
System.out.println("Closing vertx");
vertx.close();
});
});
} else {
System.out.println("Connection or Operation Failed " + r.cause());
System.out.println("Closing Redis connection");
client.close(s -> {
if (s.succeeded()) {
System.out.println("Redis closed successfully.");
} else {
System.out.println("Connection or Operation Failed " + s.cause());
}
System.out.println("Closing vertx");
vertx.close();
});
}
});
System.out.println("Exiting main");
}
}
I recommend see reactive api io.vertx.rxjava.redis.RedisClient. It's excellent(its main purposes) for the chained computation.
For example(I'm not tested this code):
client.rxSet("key", "value")
.flatMap(r -> client.rxGet("key"))
//calls on error or success
.doAfterTerminate(() -> {
client.rxClose();
vertx.close();
})
.subscribe(
success -> System.out.println("Chain completed"),
//all errors will be there
error -> System.out.println(error.getMessage())
);
Related
Integrating facebook as an auth provider within firebase (already have a working gmail implementation). The below code works fine in Unity, the FB SDK prompts for token, enter it manually, token is passed to firebase, login can be seen in the console, the required scene is then loaded.
When this is built onto an android device the full behavior doesnt happen, the correct Facebook token is received either from fresh login or existing login, we enter the SignInWithFacebookOnFirebase function to log this account into firebase and nothing else happens, sits on the debug of ("your token is " + aToken);
Im pretty sure it has something to do with the async behaviour and maybe not awaiting the task but im not sure what, any suggestions would be great !
using System.Collections.Generic;
using UnityEngine;
using Facebook.Unity;
using TMPro;
using UnityEngine.SceneManagement;
using Firebase.Auth;
using Firebase;
public class FacebookAuth : MonoBehaviour
{
private FirebaseAuth auth;
public TMP_Text debug;
void Awake ()
{
if (FB.IsInitialized) {
FB.ActivateApp();
} else {
//Handle FB.Init
FB.Init( () => {
FB.ActivateApp();
});
}
CheckFirebaseDependencies();
}
private void CheckFirebaseDependencies()
{
FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task =>
{
if (task.IsCompleted)
{
if (task.Result == DependencyStatus.Available)
auth = FirebaseAuth.DefaultInstance;
else
debug.text =("Could not resolve all Firebase dependencies: " + task.Result.ToString());
}
else
{
debug.text =("Dependency check was not completed. Error : " + task.Exception.Message);
}
});
}
void OnApplicationPause (bool pauseStatus)
{
// Check the pauseStatus to see if we are in the foreground
// or background
if (!pauseStatus) {
//app resume
if (FB.IsInitialized) {
FB.ActivateApp();
} else {
//Handle FB.Init
FB.Init( () => {
FB.ActivateApp();
});
}
}
}
private void InitCallBack()
{
if(!FB.IsInitialized)
{
FB.ActivateApp();
}
else
{
// debug.text=("Failed to initialize");
}
}
private void OnHideUnity(bool isgameshown)
{
if(!isgameshown)
{
Time.timeScale = 0;
}
else
{
Time.timeScale = 1;
}
}
public void Facebook_Login()
{
var permission = new List<string>() { "public_profile", "email" };
if (!FB.IsLoggedIn)
{
FB.LogInWithReadPermissions(permission, AuthCallBack);
}
else
{
var aToken = AccessToken.CurrentAccessToken.TokenString;
debug.text=("already logged in - starting game" + aToken);
//THIS IS THE PROBLEM ON ANDROID - ITS NOT HAPPENING/async issue?
SignInWithFacebookOnFirebase(aToken);
SceneManager.LoadScene(1);
}
}
public void LogOut()
{
FB.LogOut();
debug.text=("Logged out of facebook");
}
private void SignInWithFacebookOnFirebase(string idToken)
{
Firebase.Auth.Credential credential = Firebase.Auth.FacebookAuthProvider.GetCredential(idToken);
auth.SignInWithCredentialAsync(credential).ContinueWith(task => {
if (task.IsCanceled) {
Debug.LogError("SignInWithCredentialAsync was canceled.");
return;
}
if (task.Exception != null) {
Debug.LogWarning("SignInWithCredentialAsync encountered an error: " + task.Exception);
FirebaseException firebaseEx = task.Exception.GetBaseException() as FirebaseException;
AuthError errorCode = (AuthError)firebaseEx.ErrorCode;
string message = "Login Failed!";
switch (errorCode)
{
case AuthError.AccountExistsWithDifferentCredentials:
message = "Your account is already linked to an email address";
break;
//we can add other conditions here if required to catch exceptions
}
debug.text=(message);
}
else{
Firebase.Auth.FirebaseUser newUser = task.Result;
Debug.LogFormat("User signed in successfully: {0} ({1})",
newUser.DisplayName, newUser.UserId);
debug.text=("Logged into facebook");
}
});
}
private void AuthCallBack(ILoginResult result)
{
if(FB.IsLoggedIn)
{
var aToken = result.AccessToken.TokenString;
debug.text=("your token is " + aToken);
//THIS IS THE PROBLEM ON ANDROID - ITS NOT HAPPENING/async issue?
SignInWithFacebookOnFirebase(aToken);
debug.text=("weve signed into firebase");
SceneManager.LoadScene(1);
}
else
{
debug.text=("User Cancelled login");
}
}
}
EDIT - So the problem is nothing to do with async, its the fact that the firebase credential is being persisted on the mobile device. I uncommented all of my already working google auth code below and we log into firebase with our facebook creds fine! So i need some method of clearing our this token when A) the user logs out and B) the user closes the app (Cleanly or uncleanly) Any help would be great !
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Firebase;
using Firebase.Auth;
using Google;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class GoogleAuth : MonoBehaviour
{ /*
public TMP_Text infoText;
public string webClientId = "<your client id here>";
private FirebaseAuth auth;
private GoogleSignInConfiguration configuration;
private void Awake()
{
configuration = new GoogleSignInConfiguration { WebClientId = webClientId, RequestEmail = true, RequestIdToken = true };
CheckFirebaseDependencies();
}
private void CheckFirebaseDependencies()
{
FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task =>
{
if (task.IsCompleted)
{
if (task.Result == DependencyStatus.Available)
auth = FirebaseAuth.DefaultInstance;
else
AddToInformation("Could not resolve all Firebase dependencies: " + task.Result.ToString());
}
else
{
AddToInformation("Dependency check was not completed. Error : " + task.Exception.Message);
}
});
}
public void SignInWithGoogle() { OnSignIn(); }
public void SignOutFromGoogle() { OnSignOut(); }
private void OnSignIn()
{
GoogleSignIn.Configuration = configuration;
GoogleSignIn.Configuration.UseGameSignIn = false;
GoogleSignIn.Configuration.RequestIdToken = true;
AddToInformation("Calling SignIn");
GoogleSignIn.DefaultInstance.SignIn().ContinueWith(OnAuthenticationFinished);
}
private void OnSignOut()
{
AddToInformation("Calling SignOut");
GoogleSignIn.DefaultInstance.SignOut();
}
public void OnDisconnect()
{
GoogleSignIn.DefaultInstance.Disconnect();
infoText.text=("signed out");
}
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("Cancelled");
}
else
{
AddToInformation("Welcome: " + task.Result.DisplayName + "!");
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.");
SceneManager.LoadScene(1);
}
});
}
public void OnSignInSilently()
{
GoogleSignIn.Configuration = configuration;
GoogleSignIn.Configuration.UseGameSignIn = false;
GoogleSignIn.Configuration.RequestIdToken = true;
AddToInformation("Calling SignIn Silently");
GoogleSignIn.DefaultInstance.SignInSilently().ContinueWith(OnAuthenticationFinished);
}
public void OnGamesSignIn()
{
GoogleSignIn.Configuration = configuration;
GoogleSignIn.Configuration.UseGameSignIn = true;
GoogleSignIn.Configuration.RequestIdToken = false;
AddToInformation("Calling Games SignIn");
GoogleSignIn.DefaultInstance.SignIn().ContinueWith(OnAuthenticationFinished);
}
private void AddToInformation(string str) { infoText.text += "\n" + str; } */
}
this is solved, it was because i was checking that the firebase dependences existed in both these scripts and it was throwing an exception. I found this using the logcat logs \adb logcat -s Unity ActivityManager PackageManager dalvikvm DEBUG
I am developing an app in unity. I use the firebase google login method. basically google login is working and the user was listed in google firebase users log after login. the problem is, it is throwing an error. because of this can't fetch data from the firestore. even without firestore code, the app is showing the error
Got Error: DeveloperError Exception of type
'Google.GoogleSignIn+SignInException' was thrown
what may be the problem.
below is my code
public class GoogleSignInDemo : MonoBehaviour
{
public Text infoText;
private string webClientId = "xxxxxxaaaaaaabbbb.apps.googleusercontent.com";
private FirebaseAuth auth;
private GoogleSignInConfiguration configuration;
private void Awake()
{
configuration = new GoogleSignInConfiguration { WebClientId = webClientId, RequestEmail = true, RequestIdToken = true };
CheckFirebaseDependencies();
}
private void CheckFirebaseDependencies()
{
FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task =>
{
if (task.IsCompleted)
{
if (task.Result == DependencyStatus.Available)
auth = FirebaseAuth.DefaultInstance;
else
AddToInformation("Could not resolve all Firebase dependencies: " + task.Result.ToString());
}
else
{
AddToInformation("Dependency check was not completed. Error : " + task.Exception.Message);
}
});
}
public void SignInWithGoogle() { OnSignIn(); }
public void SignOutFromGoogle() { OnSignOut(); }
private void OnSignIn()
{
GoogleSignIn.Configuration = configuration;
GoogleSignIn.Configuration.UseGameSignIn = false;
GoogleSignIn.Configuration.RequestIdToken = true;
AddToInformation("Calling SignIn");
GoogleSignIn.DefaultInstance.SignIn().ContinueWith(OnAuthenticationFinished);
}
private void OnSignOut()
{
AddToInformation("Calling SignOut");
GoogleSignIn.DefaultInstance.SignOut();
}
public void OnDisconnect()
{
AddToInformation("Calling Disconnect");
GoogleSignIn.DefaultInstance.Disconnect();
}
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("Email = " + task.Result.Email);
AddToInformation("Google ID Token = " + task.Result.IdToken);
AddToInformation("Email = " + task.Result.Email);
SignInWithGoogleOnFirebase(task.Result.IdToken);
SceneManager.LoadScene(1); //Savad - Load Welcome screen when Google Login
}
}
private void SignInWithGoogleOnFirebase(string idToken)
{
Credential credential = GoogleAuthProvider.GetCredential(idToken, null);
auth.SignInWithCredentialAsync(credential).ContinueWith(task =>
{
AggregateException ex = task.Exception;
//==============Here is the problem
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.");
}
});
}
public void OnSignInSilently()
{
GoogleSignIn.Configuration = configuration;
GoogleSignIn.Configuration.UseGameSignIn = false;
GoogleSignIn.Configuration.RequestIdToken = true;
AddToInformation("Calling SignIn Silently");
GoogleSignIn.DefaultInstance.SignInSilently().ContinueWith(OnAuthenticationFinished);
}
public void OnGamesSignIn()
{
GoogleSignIn.Configuration = configuration;
GoogleSignIn.Configuration.UseGameSignIn = true;
GoogleSignIn.Configuration.RequestIdToken = false;
AddToInformation("Calling Games SignIn");
GoogleSignIn.DefaultInstance.SignIn().ContinueWith(OnAuthenticationFinished);
}
private void AddToInformation(string str) { infoText.text += "\n" + str; }
public void SwitchToPhoneSignup()
{
SceneManager.LoadScene(2);
}
public void SwitchToOtp()
{
SceneManager.LoadScene(2);
}
public void SwitchToEmailSignUP()
{
SceneManager.LoadScene(2);
}
}
Here is a working example of Google SignIn code w/ Firebase Authentication and GoogleSignIn libraries:
private void SignInWithGoogle(bool linkWithCurrentAnonUser)
{
GoogleSignIn.Configuration = new GoogleSignInConfiguration
{
RequestIdToken = true,
// Copy this value from the google-service.json file.
// oauth_client with type == 3
WebClientId = "[YOUR API CLIENT ID HERE].apps.googleusercontent.com"
};
Task<GoogleSignInUser> signIn = GoogleSignIn.DefaultInstance.SignIn();
TaskCompletionSource<FirebaseUser> signInCompleted = new TaskCompletionSource<FirebaseUser>();
signIn.ContinueWith(task =>
{
if (task.IsCanceled)
{
signInCompleted.SetCanceled();
}
else if (task.IsFaulted)
{
signInCompleted.SetException(task.Exception);
}
else
{
Credential credential = Firebase.Auth.GoogleAuthProvider.GetCredential(((Task<GoogleSignInUser>)task).Result.IdToken, null);
if (linkWithCurrentAnonUser)
{
mAuth.CurrentUser.LinkWithCredentialAsync(credential).ContinueWith(HandleLoginResult);
}
else
{
SignInWithCredential(credential);
}
}
});
}
The parameter is for signing in with intentions of linking the new google account with an anonymous user that is currently logged on. You can ignore those parts of the method if desired. Please note all of this is called after proper initialization of the Firebase Auth libraries.
Source: https://github.com/googlesamples/google-signin-unity
The readme page contains a step-by-step instructions for getting this setup for your environment. After following those and using the code above, you should have this working on both android and iOS.
Here is the SignInWithCredential method used in the code above:
private void SignInWithCredential(Credential credential)
{
if (mAuth != null)
{
mAuth.SignInWithCredentialAsync(credential).ContinueWith(HandleLoginResult);
}
}
`mAuth` is a reference to FirebaseAuth:
mAuth = Firebase.Auth.FirebaseAuth.DefaultInstance;
For someone asking for the HandleLoginResult from #DIGI Byte, here is the code, feel free to remove try/catch block for debug purpose:
private void HandleLoginResult(Task<FirebaseUser> task)
{
try
{
if (task.IsCanceled)
{
UnityEngine.Debug.LogError("SignInWithCredentialAsync was canceled.");
return;
}
if (task.IsFaulted)
{
UnityEngine.Debug.LogError("SignInWithCredentialAsync encountered an error: " + task.Exception.InnerException.Message);
return;
}
else
{
FirebaseUser newUser = task.Result;
UnityEngine.Debug.Log($"User signed in successfully: {newUser.DisplayName} ({newUser.UserId})");
}
}
catch (Exception e)
{
if (e != null)
{
UnityEngine.Debug.Log(e.InnerException.Message);
}
}
}
You have Error like: got error developer error exception of type 'google.googlesignin+signin exception' was thrown?
APK and AAB file have different SHA1 and SHA256. In Firebase, it's best to add SHA for both applications.
You can check the SHA from the AAB file in Google Play Console -> Your application -> Configuration -> Application integrity -> Application signing.
I added these SHA keys to Firebase and the problem was gone.
I am using FirebaseFunctions as well as https://github.com/voltrue2/in-app-purchase to validate purchases. I am having trouble sending the data back to my client. In the logs of my functions everything goes well and I get the result I want, but as I understand you have to return a promise in order to get the data back to the client when using Firebase's onCall https trigger. The code for my oncall trigger is here.
var iap = require('in-app-purchase');
var purchaseData;
const receipt = data;
iap.config({
googlePublicKeyPath: 'acualpublickey' ,
googleAccToken: 'actualtoken',
googleRefToken: 'actualtoken',
googleClientID: 'actualID',
googleClientSecret: 'actual seceret',
});
iap.setup()
.then(() => {
console.log("receipt: ", receipt)
return iap.validate(receipt).then(onSuccess).catch(onError);
}).catch((error) => {
console.log("error setup: " + error);
throw error;
});
function onSuccess(validatedData) {
var options = {
ignoreExpired: true // purchaseData will NOT contain exipired subscription items
};
purchaseData = iap.getPurchaseData(validatedData, options);
console.log("PurchseData : ", purchaseData);
console.log("ValidatedData : ", validatedData);
return purchaseData;
}
function onError(error) {
console.log("error onError: " + error);
throw error;
}
the function it is called on to be used is this one
void receiptJSONvalidation(String receipt){
if (receipt != null) {
try {
JSONObject jsonObject = new JSONObject(receipt);
Task<Object> validatedReceipt = validation(jsonObject);
validatedReceipt.addOnCompleteListener(this, new OnCompleteListener<Object>() {
#Override
public void onComplete(#NonNull Task<Object> task) {
if (!task.isSuccessful()) {
Exception e = task.getException();
if (e instanceof FirebaseFunctionsException) {
FirebaseFunctionsException ffe = (FirebaseFunctionsException) e;
FirebaseFunctionsException.Code code = ffe.getCode();
Object details = ffe.getDetails();
errorAlert("task unsuccessful: " + details.toString());
} else {
errorAlert("Error onComplete: " + e.getLocalizedMessage());
}
// ...
} else{
Gson gson = new Gson();
String taskResult = gson.toJson(task.getResult());
errorAlert("taskResult: " + taskResult);
}
}
});
} catch (JSONException e) {
errorAlert("Error Json: " + e.getLocalizedMessage());
}
} else {
errorAlert("You are not subscribed. Please purchase a subscription.");
}
}
the validation method is this
private Task<Object> validation(JSONObject receipt){
mFunctions = FirebaseFunctions.getInstance();
return mFunctions.getHttpsCallable("receiptValidation").call(receipt)
.continueWith(new Continuation<HttpsCallableResult,Object>() {
public Object then(#NonNull Task<HttpsCallableResult> task) throws Exception {
// This continuation runs on either success or failure, but if the task
// has failed then getResult() will throw an Exception which will be
// propagated down.
Object result = task.getResult().getData();
return result;
}
});
}
When I get to both taskResult and result I am getting null while my logs have the actual data I need. I tried to follow the documentation for these functions yet I still don't get what is needed. Also there seems to be a problem with my app not allowing the firebase function to finish. Sometimes the result pops up null before the function is even over. The function will say it took about 8 sec. Yet the alert pops up in way less time.
I am receiving strings from my server that I want to append into a Textarea on the client side (Think chat window). Problem is, when I receive the string, the client freezes.
insertUserNameButton.setOnAction((event) -> {
userName=userNameField.getText();
try {
connect();
} catch (IOException e) {
e.printStackTrace();
}
});
public Client() {
userInput.setOnAction((event) -> {
out.println(userInput.getText());
userInput.setText("");
});
}
private void connect() throws IOException {
String serverAddress = hostName;
Socket socket = new Socket(serverAddress, portNumber);
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
while (true) {
String line = in.readLine();
if (line.startsWith("SUBMITNAME")) {
out.println(userName);
} else if (line.startsWith("MESSAGE")) {
Platform.runLater(()->serverOutput.appendText(line.substring(8) + "\n"));
} else if (line.startsWith("QUESTION")) {
Platform.runLater(()->serverOutput.appendText(line.substring(8) + "\n"));
} else if (line.startsWith("CORRECTANSWER")) {
Platform.runLater(()->serverOutput.appendText(line.substring(14) + "\n"));
}
}
}
public static void main(String[] args) {
launch(args);
}
I have done some research and it seems that using Platform.runLater on each append should fix the problem. It doesn't for me.
Anyone has an idea of what it can be caused by? Thank you!
You are calling connect() on the FX Application Thread. Since it blocks indefinitely via the
while(true) {
String line = in.readLine();
// ...
}
construct, you block the FX Application Thread and prevent it from doing any of its usual work (rendering the UI, responding to user events, etc).
You need to run this on a background thread. It's best to use a Executor to manage the threads:
private final Executor exec = Executors.newCachedThreadPool(runnable -> {
Thread t = new Thread(runnable);
t.setDaemon(true);
return t ;
});
and then do
insertUserNameButton.setOnAction((event) -> {
userName=userNameField.getText();
exec.execute(() -> {
try {
connect();
} catch (IOException e) {
e.printStackTrace();
}
});
});
I am getting an exception that "The connection has not been established" when I try to invoke my hub class method using IHubProxy and I am unable figure out the issue. The connection has been made successful but the following line of code throw an error.
hubProxy.Invoke("SendNotificationToUser", new object[] { touser, message }).ContinueWith(task =>
{
if (task.IsFaulted && task.Exception != null)
{
// log error
}
});
here's my complete code..
[WebMethod]
public static void NotfTest(string message)
{
var hubConnection = new HubConnection("http://localhost:3052/CollegeBuilder/");
IHubProxy hubProxy = hubConnection.CreateHubProxy("NotificationHub");
var touser = "128";
try
{
lock (hubConnection)
{
if (hubConnection.State == Microsoft.AspNet.SignalR.Client.ConnectionState.Disconnected)
{
hubConnection.Start().Wait(2000);
}
}
hubProxy.Invoke("SendNotificationToUser", new object[] { touser, message }).ContinueWith(task =>
{
if (task.IsFaulted && task.Exception != null)
{
// log error
}
}); ;
}
finally
{
hubConnection.Stop();
}
}
In order to debug your situation you should enable detailed errors. See here for more information: http://www.asp.net/signalr/overview/signalr-20/hubs-api/hubs-api-guide-javascript-client#handleerrors