Xamarin.Azure.Notification.Hub (3.1.1) crashing in iOS 16.1 - xamarin.forms

public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
try
{
string ConnectionString = AppConfiguration.NotificationHubConnectionString;
string hubPath = AppConfiguration.NotificationHubPath;
if (!string.IsNullOrEmpty(ApplicationContext.Instance.APIVersion))
{
ConnectionString = AppConfiguration.NotificationHubConnectionStringv2;
hubPath = AppConfiguration.NotificationHubPath2;
}
NSSet tags = null;
SBNotificationHub hub;
byte[] bytes = deviceToken.ToArray();
string[] hexArray = bytes.Select(b => b.ToString("x2")).ToArray();
var tokenString = string.Join(string.Empty, hexArray);
hub = new SBNotificationHub(ConnectionString, hubPath);
tags = new NSSet(new string[] {
Mvx.IoCProvider.Resolve<IDeviceIdentifier>()?.GetRestaurantId()?.ToLower() });
hub.UnregisterAll(deviceToken, error =>
{
if (error != null)
{
LazyServiceFromIOC<IAnalytics>.Instance.RequestedService?.LogEvent(Enums.CustomEvents.Notifications.ToString(), error.Description);
return;
}
hub.RegisterNative(deviceToken, tags, errorCallback =>
{
if (errorCallback != null)
{
LazyServiceFromIOC<IAnalytics>.Instance.RequestedService?.LogEvent(Enums.CustomEvents.Notifications.ToString(), errorCallback.Description);
}
});
});
Preferences.Set("DeviceTokens", tokenString);
PushNotificationManager.DidRegisterRemoteNotifications(deviceToken);
}
catch (Exception ex)
{
LazyServiceFromIOC<IAnalytics>.Instance.RequestedService?.LogException(nameof(RegisteredForRemoteNotifications), ex);
}
}
Xamarin.Azure.Notification.Hub (3.1.1) - iOS 16.1
App is crashing at RegisterNative method... This logic was working all this while..till ios was upgraded to 16 on ipad
What changed in iOS 16

Related

Your app(s) are using a WebView that is vulnerable to cross-app scripting

My android app keeps getting rejected because of this reason:
Your app(s) are using a WebView that is vulnerable to cross-app scripting.
I already did an extensive search and found some thing I could do:
Follow the steps on https://support.google.com/faqs/answer/9084685. Since I'm using a launcher, I have to follow option 2.
I added this code in my manifest.xml: android.webkit.WebView.EnableSafeBrowsing
I'm sure the problem lies in the code posted below, where I don't use a fixed url for my loadURL, but I let it change via intent, being a notificiation url or a mail link. I'm aware this gives serious security issues, but I don't know how to fix it. In the link I provided above I want to follow option 2 but:
I can't disable javascript (my webpage won't load without it)
I don't know how to validate/secure the url in loadURL in such a way that Google allows me to upload my app to the Play Store.
Can someone please help me?
#Override
protected void onCreate(Bundle savedInstanceState) {
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
new IntentFilter("send-url"));
super.onCreate(savedInstanceState);
setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(R.layout.activity_main);
String default_url = "https://www.playday.be/app/";
FirebaseMessaging.getInstance().getToken()
.addOnCompleteListener(task -> {
if (task.isSuccessful() && task.getResult() != null) {
String refreshedToken = task.getResult();
Log.v("newToken",refreshedToken);
sendRegistrationToServer(refreshedToken);
}
});
if(getIntent().getExtras() != null){
if (getIntent().getExtras().getString("pushUrl") != null) {
String url_from_notif = getIntent().getExtras().getString("pushUrl");
if(Patterns.WEB_URL.matcher(url_from_notif).matches()) {
default_url = url_from_notif;
Log.v("url_from_notif = ", default_url);
}
}
if (getIntent().getData() != null) {
String url_from_mail = getIntent().getData().toString();
url_from_mail = url_from_mail.replace("playday://", "");
if(Patterns.WEB_URL.matcher(url_from_mail).matches()) {
default_url = url_from_mail;
Log.v("url_from_mail = ", default_url);
}
}
}
Log.v("default_url_new = ", "" +default_url);
webView = findViewById(R.id.ifView);
assert webView != null;
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setAllowFileAccess(true);
webSettings.setGeolocationEnabled(false);
webView.setWebViewClient(new Callback());
webView.setWebViewClient(new MyAppWebViewClient(){
public void onReceivedError(WebView webView, int errorCode, String description, String failingUrl) {
try {
webView.stopLoading();
} catch (Exception e) {
Log.v("method:", "onReceivedError");
}
if (webView.canGoBack()) {
webView.goBack();
}
webView.loadUrl("about:blank");
AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this).create();
alertDialog.setTitle("Je bent niet online...");
alertDialog.setIcon(R.mipmap.ic_launcher);
alertDialog.setMessage("Gelieve je internetconnectie te herstellen en probeer dan opnieuw.");
alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, "Probeer opnieuw", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
finish();
startActivity(getIntent());
}
});
try {
alertDialog.show();
} catch(Exception e){
Log.e(TAG,"show dialog error no internet connection");
}
super.onReceivedError(webView, errorCode, description, failingUrl);
}
});
webView.loadUrl(default_url);
webView.setWebChromeClient(new WebChromeClient() {
public boolean onShowFileChooser(WebView view, ValueCallback<Uri[]> filePath, WebChromeClient.FileChooserParams fileChooserParams) {
Log.d(TAG,"111 ShowFileChooser For Android 5.0 ");
if (Build.VERSION.SDK_INT >= 23) {
if (mUMA != null) {
mUMA.onReceiveValue(null);
}
mUMA = filePath;
Log.d(TAG,"ShowFileChooser For Android 5.0 SDK_INT>=23 chk permission");
String[] PERMISSIONS = {android.Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, android.Manifest.permission.CAMERA};
if (!hasPermissions(mContext, PERMISSIONS)) {
ActivityCompat.requestPermissions((Activity) mContext, PERMISSIONS, REQUEST_CAMERA);
} else {
Log.d(TAG,"112 ShowFileChooser For Android 5.0 in IF SDK_INT>=23 permission grant");
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
takePictureIntent.putExtra("PhotoPath", mCM);
} catch (Exception ex) {
// Error occurred while creating the File
Log.e(TAG, "Unable to create Image File 1", ex);
}
// Continue only if the File was successfully created
if (photoFile != null) {
mCM = "file:" + photoFile.getAbsolutePath();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
} else {
takePictureIntent = null;
}
}
Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
contentSelectionIntent.setType("image/*");
Intent[] intentArray;
if (takePictureIntent != null) {
intentArray = new Intent[]{takePictureIntent};
} else {
intentArray = new Intent[0];
}
Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
startActivityForResult(chooserIntent, FCR);
}
} else {
Log.d(TAG,"113 ShowFileChooser For Android 5.0 in else SDK_INT>=23");
if (mUMA != null) {
mUMA.onReceiveValue(null);
}
mUMA = filePath;
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
takePictureIntent.putExtra("PhotoPath", mCM);
} catch (Exception ex) {
// Error occurred while creating the File
Log.e(TAG, "Unable to create Image File 2", ex);
}
// Continue only if the File was successfully created
if (photoFile != null) {
mCM = "file:" + photoFile.getAbsolutePath();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
} else {
takePictureIntent = null;
}
}
Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
contentSelectionIntent.setType("image/*");
Intent[] intentArray;
if (takePictureIntent != null) {
intentArray = new Intent[]{takePictureIntent};
} else {
intentArray = new Intent[0];
}
Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
startActivityForResult(chooserIntent, FCR);
}
// Double check that we don't have any existing callbacks
return true;
}
});
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
String channelId = "1";
String channel2 = "2";
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel(channelId,
"Channel 1", NotificationManager.IMPORTANCE_HIGH);
notificationChannel.setDescription("This is BNT");
notificationChannel.setLightColor(Color.RED);
notificationChannel.enableVibration(true);
notificationChannel.setShowBadge(true);
assert notificationManager != null; //edit 1402
notificationManager.createNotificationChannel(notificationChannel);
NotificationChannel notificationChannel2 = new NotificationChannel(channel2,
"Channel 2", NotificationManager.IMPORTANCE_MIN);
notificationChannel.setDescription("This is bTV");
notificationChannel.setLightColor(Color.RED);
notificationChannel.enableVibration(true);
notificationChannel.setShowBadge(true);
notificationManager.createNotificationChannel(notificationChannel2);
}
}
I finally figured it out myself and got my app approved in the app store.
I just needed to validate/sanitize the url that was loaded in the webview.
I changed the code:
if(getIntent().getExtras() != null){
if (getIntent().getExtras().getString("pushUrl") != null) {
String url_from_notif = getIntent().getExtras().getString("pushUrl");
if(Patterns.WEB_URL.matcher(url_from_notif).matches()) {
default_url = url_from_notif;
Log.v("url_from_notif = ", default_url);
}
}
if (getIntent().getData() != null) {
String url_from_mail = getIntent().getData().toString();
url_from_mail = url_from_mail.replace("playday://", "");
if(Patterns.WEB_URL.matcher(url_from_mail).matches()) {
default_url = url_from_mail;
Log.v("url_from_mail = ", default_url);
}
}
}
To:
if(getIntent().getExtras() != null){
String url_from_notif = getIntent().getExtras().getString("pushUrl");
if (url_from_notif != null) {
if(URLUtil.isValidUrl(url_from_notif) && Patterns.WEB_URL.matcher(url_from_notif).matches()) {
default_url = url_from_notif;
Log.v("url_from_notif = ", default_url);
}
}
if (getIntent().getData() != null) {
String url_from_mail = getIntent().getData().toString();
url_from_mail = url_from_mail.replace("playday://", "");
if(URLUtil.isValidUrl(url_from_mail) && Patterns.WEB_URL.matcher(url_from_mail).matches()) {
default_url = url_from_mail;
Log.v("url_from_mail = ", default_url);
}
}
}
And:
webView.loadUrl(default_url);
To:
URI uri;
try {
uri = new URI(default_url);
String domain = uri.getHost();
if (!default_url.startsWith("https://www.playday.be") || !domain.equals("www.playday.be") || !URLUtil.isValidUrl(default_url) || !Patterns.WEB_URL.matcher(default_url).matches()) {
webView.loadUrl("about:blank");
} else {
webView.loadUrl(default_url);
}
} catch (URISyntaxException e) {
e.printStackTrace();
}

Unity Firebase Facebook auth on Android

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

Got Error: DeveloperError Exception of type 'Google.GoogleSignIn+SignInException' was thrown --- unity, firebase, google login?

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.

Merging more than 2 accounts into one

I have a quite strange or somewhat understandable(?) problem.
My firebase project support 4 types of authentications: Google, Apple, Facebook and anonymous.
I created 2 accounts. One has Google linked with facebook, the other one has apple only.
Then I link same facebook account that is already linked with google at apple account.
Firebase console shows no change but everytime I login into apple account, firebase returns google's UID.
I kinda understand that there are all linked into one account but I don't get why the apple's UID isn't removed and google's UID doesn't have apple provider from firebase console.
Another case:
Create 3 accounts: Google, Apple and Facebook separately.
Link all together into one. every time whichever I login into, firebase returns facebook's UID. (this is something that I completely unable to understand why.)
If it's normal, should I manage them manually on console or my project if I want to see it as one account on firebase console?
Edit:
firebase console
Unity FirebaseAuth.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Firebase.Auth;
using System.Text;
using System.Security.Cryptography;
using UnityEngine.SocialPlatforms;
#if !UNITY_IOS
using GooglePlayGames;
using GooglePlayGames.BasicApi;
using GooglePlayGames.OurUtils;
#else
using AppleAuth;
using AppleAuth.Native;
using AppleAuth.Enums;
using AppleAuth.Extensions;
using AppleAuth.Interfaces;
#endif
public class FirebaseAuth : MonoBehaviour
{
public enum eMOBILEPLATFORM_STATUS
{
CONNECTED,
DISCONNECT,
ERROR,
LOGIN_WAIT,
};
private static FirebaseAuth _instance;
protected eMOBILEPLATFORM_STATUS _accountStatus = eMOBILEPLATFORM_STATUS.DISCONNECT;
#if UNITY_IOS
private IAppleAuthManager _appleAuthManager;
#endif
public eMOBILEPLATFORM_STATUS Status { get { return _accountStatus; } }
public FirebaseAuth auth;
private string _accessToken = string.Empty;
public static FirebaseAuth Instance
{
get
{
if (_instance == null)
{
_instance = FindObjectOfType(typeof(FirebaseAuth)) as FirebaseAuth;
if (_instance == null)
{
Debug.LogError("Missing GlobalObject, Use for Firebase");
return null;
}
}
return _instance;
}
}
void Update()
{
#if UNITY_IOS
if (_appleAuthManager != null) _appleAuthManager.Update();
#endif
}
public void Init()
{
#if !UNITY_IOS
PlayGamesClientConfiguration config = new PlayGamesClientConfiguration
.Builder()
.RequestServerAuthCode(false)
.RequestIdToken()
.Build();
PlayGamesPlatform.InitializeInstance(config);
PlayGamesPlatform.DebugLogEnabled = true;
PlayGamesPlatform.Activate();
#else
if (AppleAuthManager.IsCurrentPlatformSupported)
{
var deserializer = new PayloadDeserializer();
_appleAuthManager = new AppleAuthManager(deserializer);
}
#endif
Debug.Log("Firebase Init");
auth = FirebaseAuth.DefaultInstance;
_accessToken = string.Empty;
}
#if !UNITY_IOS
public void TryGoogleLogin(bool newLogin = true)
{
if (!Social.localUser.authenticated)
{
Social.localUser.Authenticate(success =>
{
if (success)
{
Debug.Log("login success. " + Social.localUser.userName);
if (newLogin)
{
StartCoroutine(TryGoogleFirebaseLogin(newLogin));
}
else
{
LinkGoogleFirebase();
}
}
else
{
Debug.Log("login failed");
}
});
}
else
{
if (newLogin)
{
StartCoroutine(TryGoogleFirebaseLogin(newLogin));
}
else
{
LinkGoogleFirebase();
}
}
}
public void TryGoogleLogout()
{
if (Social.localUser.authenticated)
{
PlayGamesPlatform.Instance.SignOut();
TryFirebaseLogout();
Debug.Log("logout - done");
}
}
public IEnumerator TryGoogleFirebaseLogin(bool newLogin = true)
{
if (newLogin)
{
auth.Dispose();
auth = FirebaseAuth.DefaultInstance;
}
while (string.IsNullOrEmpty(((PlayGamesLocalUser)Social.localUser).GetIdToken()))
yield return null;
string idToken = ((PlayGamesLocalUser)Social.localUser).GetIdToken();
_accessToken = idToken;
Credential credential = GoogleAuthProvider.GetCredential(idToken, null);
auth.SignInWithCredentialAsync(credential).ContinueWith(task =>
{
if (task.IsCanceled)
{
Debug.LogError("google-CredentialAsync was canceled.");
return;
}
if (task.IsFaulted)
{
Debug.LogError("google-CredentialAsync encountered and error: " + task.Exception);
return;
}
Debug.Log("google login success! :D " + auth.CurrentUser.UserId);
_accountStatus = eMOBILEPLATFORM_STATUS.CONNECTED;
UserConfig.Instance.SaveMobilePlatformLogin(true);
PlayerInfo.Instance.m_bGlobalMobilePlatformLogin = true;
if (DoesProvierExist("facebook.com"))
{
PlayerInfo.Instance.m_bGlobalGuestLogin = false;
UserConfig.Instance.SaveFacebookLogin(true);
FacebookManager.Instance.ChangeFacebookStatus(FacebookManager.eFACEBOOK_STATUS.CONNECTED);
}
});
}
public void LinkGoogleFirebase()
{
if (auth != null)
{
string idToken = ((PlayGamesLocalUser)Social.localUser).GetIdToken();
Credential credential = GoogleAuthProvider.GetCredential(idToken, null);
auth.CurrentUser.LinkWithCredentialAsync(credential).ContinueWith(task =>
{
if (task.IsCanceled)
{
Debug.LogError("google-LinkWithCredentialAsync was canceled.");
return;
}
if (task.IsFaulted)
{
Debug.LogError("google-LinkWithCredentialAsync encountered an error: " + task.Exception);
return;
}
FirebaseUser newUser = task.Result;
Debug.Log("google-Credentials successfully linked to Firebase user: " + newUser.DisplayName + "(" + newUser.UserId + ")");
_accountStatus = eMOBILEPLATFORM_STATUS.CONNECTED;
});
}
}
#endif
public IEnumerator TryFacebookFirebaseLogin(Facebook.Unity.AccessToken accessToken, bool newLogin = false)
{
if (newLogin)
{
auth = FirebaseAuth.DefaultInstance;
}
while (System.String.IsNullOrEmpty(accessToken.TokenString))
yield return null;
_accessToken = accessToken.TokenString;
auth = FirebaseAuth.DefaultInstance;
Credential credential = FacebookAuthProvider.GetCredential(accessToken.TokenString);
auth.SignInWithCredentialAsync(credential).ContinueWith(task =>
{
if (task.IsCanceled)
{
Debug.LogError("facebook-CredentialAsync was canceled.");
return;
}
if (task.IsFaulted)
{
Debug.LogError("facebook-CredentialAsync encountered and error: " + task.Exception);
return;
}
Debug.Log("facebook firebase success! :D " + auth.CurrentUser.UserId);
#if !UNITY_IOS
if(DoesProvierExist("google.com"))
#else
if(DoesProvierExist("apple.com"))
#endif
{
_accountStatus = eMOBILEPLATFORM_STATUS.CONNECTED;
}
});
}
public void LinkFacebookFirebase(Facebook.Unity.AccessToken accessToken)
{
if (auth != null)
{
Credential credential = FacebookAuthProvider.GetCredential(accessToken.TokenString);
auth.CurrentUser.LinkWithCredentialAsync(credential).ContinueWith(task =>
{
if (task.IsCanceled)
{
Debug.LogError("facebook-LinkWithCredentialAsync was canceled.");
return;
}
if (task.IsFaulted)
{
Debug.LogError("facebook-LinkWithCredentialAsync encountered an error: " + task.Exception);
return;
}
FirebaseUser newUser = task.Result;
Debug.Log("facebook-Credentials successfully linked to Firebase user: " + newUser.DisplayName + "(" + newUser.UserId + ")");
FacebookManager.Instance.ChangeFacebookStatus(FacebookManager.eFACEBOOK_STATUS.CONNECTED);
});
}
}
#if UNITY_IOS
public IEnumerator TryAppleFirebaseLogin(bool newLogin = true)
{
if (newLogin)
{
auth.Dispose();
auth = FirebaseAuth.DefaultInstance;
}
string rawNonce = GenerateRandomString(32);
string nonce = GenerateSHA256NonceFromRawNonce(rawNonce);
var loginArgs = new AppleAuthLoginArgs(LoginOptions.IncludeEmail | LoginOptions.IncludeFullName, nonce);
while (auth==null)
yield return null;
_appleAuthManager.LoginWithAppleId(
loginArgs,
credential =>
{
var appleIdCredential = credential as IAppleIDCredential;
var identityToken = Encoding.UTF8.GetString(appleIdCredential.IdentityToken);
var authorizationCode = Encoding.UTF8.GetString(appleIdCredential.AuthorizationCode);
var firebaseCredential = OAuthProvider.GetCredential("apple.com", identityToken, rawNonce, authorizationCode);
auth.SignInWithCredentialAsync(firebaseCredential);
if (appleIdCredential.FullName != null)
{
var userName = appleIdCredential.FullName.ToLocalizedString();
var profile = new UserProfile();
profile.DisplayName = userName;
auth.CurrentUser.UpdateUserProfileAsync(profile);
}
_accessToken = authorizationCode.ToString();
Debug.Log("apple firebase success! :D " + auth.CurrentUser.UserId);
_accountStatus = eMOBILEPLATFORM_STATUS.CONNECTED;
UserConfig.Instance.SaveMobilePlatformLogin(true);
PlayerInfo.Instance.m_bGlobalMobilePlatformLogin = true;
if (DoesProvierExist("facebook.com"))
{
PlayerInfo.Instance.m_bGlobalGuestLogin = false;
UserConfig.Instance.SaveFacebookLogin(true);
}
},
error =>
{
var authorizationErrorCode = error.GetAuthorizationErrorCode();
switch (authorizationErrorCode)
{
case AuthorizationErrorCode.Canceled:
break;
case AuthorizationErrorCode.Unknown:
case AuthorizationErrorCode.InvalidResponse:
case AuthorizationErrorCode.NotHandled:
case AuthorizationErrorCode.Failed:
Debug.LogError("apple-login failed :/ error code: " + authorizationErrorCode);
break;
}
return;
});
}
#endif
public IEnumerator TryGuestFirebaseLogin(bool newLogin = false)
{
if (newLogin)
{
auth.Dispose();
auth = FirebaseAuth.DefaultInstance;
}
while (auth == null)
yield return null;
auth.SignInAnonymouslyAsync().ContinueWith(task =>
{
if (task.IsCanceled)
{
Debug.LogError("guest-SignInAnonymouslyAsync was canceled.");
return;
}
if (task.IsFaulted)
{
Debug.LogError("guest-SignInAnonymouslyAsync encountered an error: " + task.Exception);
return;
}
Firebase.Auth.FirebaseUser newUser = task.Result;
Debug.Log("guest-User signed in successfully :D " + newUser.DisplayName + " (" + newUser.UserId + ")");
});
}
public void UnlinkFirebase(string providerID)
{
if (auth != null && DoesProvierExist(providerID))
{
auth.CurrentUser.UnlinkAsync(providerID).ContinueWith(task =>
{
if (task.IsCanceled)
{
Debug.LogError(providerID + "-UnlinkAsync was canceled.");
return;
}
if (task.IsFaulted)
{
Debug.LogError(providerID + "-UnlinkAsync encountered an error: " + task.Exception);
return;
}
// The user has been unlinked from the provider.
FirebaseUser newUser = task.Result;
Debug.LogFormat(providerID + " Credentials successfully unlinked from user: {0} ({1})", newUser.DisplayName, newUser.UserId);
#if !UNITY_IOS
if (providerID == "google.com")
#else
if (providerID == "apple.com")
#endif
{
_accountStatus = eMOBILEPLATFORM_STATUS.DISCONNECT;
}
});
}
}
public void TryFirebaseLogout()
{
auth.SignOut();
}
private string GenerateRandomString(int length)
{
const string charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._";
var cryptographicallySecureRandomNumberGenerator = new RNGCryptoServiceProvider();
var result = string.Empty;
var remainingLength = length;
var randomNumberHolder = new byte[1];
while (remainingLength > 0)
{
var randomNumbers = new List<int>(16);
for (var randomNumberCount = 0; randomNumberCount < 16; randomNumberCount++)
{
cryptographicallySecureRandomNumberGenerator.GetBytes(randomNumberHolder);
randomNumbers.Add(randomNumberHolder[0]);
}
for (var randomNumberIndex = 0; randomNumberIndex < randomNumbers.Count; randomNumberIndex++)
{
if (remainingLength == 0)
{
break;
}
var randomNumber = randomNumbers[randomNumberIndex];
if (randomNumber < charset.Length)
{
result += charset[randomNumber];
remainingLength--;
}
}
}
return result;
}
private string GenerateSHA256NonceFromRawNonce(string rawNonce)
{
var sha = new SHA256Managed();
var utf8RawNonce = Encoding.UTF8.GetBytes(rawNonce);
var hash = sha.ComputeHash(utf8RawNonce);
var result = string.Empty;
for (var i = 0; i < hash.Length; i++)
{
result += hash[i].ToString("x2");
}
return result;
}
public string GetAccessToken()
{
return _accessToken;
}
/// <summary>
/// Check the current user has certain provierID.
/// </summary>
/// <param name="providerID"> Such as "facebook.com", "apple.com", "google.com"</param>
/// <returns>false if auth or user is null</returns>
public bool DoesProvierExist(string providerID)
{
FirebaseUser user = auth.CurrentUser;
bool result = false;
int checkCount = 0;
List<string> providers = new List<string>();
if (user != null)
{
foreach (var profile in user.ProviderData)
{
checkCount++;
providers.Add(profile.ProviderId);
if (profile.ProviderId == providerID)
result = true;
}
}
#if _USE_DEBUG_LOG_
string temp = string.Empty;
for (int i = 0; i < providers.Count; i++)
{
temp += providers[i];
if (i != providers.Count - 1)
temp += ", ";
}
Debug.Log("Just in case if you wanna know. There are " + checkCount + " providerID at this account\n"+temp);
#endif
return result;
}
}
and here's xcode log of iphone.
ClickButton (GlobalStart)(04/16/2021 10:22:56)
UIEventButtonClick:OnClick()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
LoginFacebook()False
FacebookManager:LoginFacebook()
UIL_Login:Event_Click(String)
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
2021-04-16 10:22:56.640715+0900 firebaseProject[1006:67274] -canOpenURL: failed for URL: "fbauth2:/" - error: "The operation couldn’t be completed. (OSStatus error -10814.)"
-> applicationWillResignActive()
-> applicationDidBecomeActive()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
2021-04-16 10:22:58.701301+0900 firebaseProject[1006:68330] [tcp] tcp_input [C19.1:3] flags=[R] seq=3046356287, ack=0, win=0 state=CLOSED rcv_nxt=3046356287, snd_una=716434727
2021-04-16 10:22:58.705125+0900 firebaseProject[1006:68330] [tcp] tcp_input [C19.1:3] flags=[R] seq=3046356287, ack=0, win=0 state=CLOSED rcv_nxt=3046356287, snd_una=716434727
CONNECTTING() True
FacebookManager:Connectting()
Facebook.Unity.CallbackManager:TryCallCallback(Object, IResult)
Facebook.Unity.CallbackManager:CallCallback(Object, IResult)
Facebook.Unity.CallbackManager:OnFacebookResponse(IInternalResult)
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
facebook-LinkWithCredentialAsync encountered an error: System.AggregateException: Exception of type 'System.AggregateException' was thrown.
-----------------
Firebase.FirebaseException: [ERROR_PROVIDER_ALREADY_LINKED] - User can only be linked to one identity for the given provider.
System.Threading.Tasks.<ContinueWith>c__AnonStorey0:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey2:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey1:<>m__0()
System.Threading.Tasks.Task:<immediateExecutor>m__1(Action)
System.Threading.Tasks.Task`1:RunContinuations()
System.Threading.Tasks.Task`1:TrySetException(AggregateException)
System.Threading.Tasks.TaskCompletionSource`1:SetException(Exception)
Firebase.Auth.<GetTask>c__AnonStorey0:<>m__0()
Firebase.Auth.Future_User:SWIG_CompletionDispatcher(Int32)
Firebase.AppUtil:PollCallbacks()
Firebase.Platform.FirebaseHandler:Update()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
2021-04-16 10:23:01.367311+0900 firebaseProject[1006:67777] [tcp] tcp_input [C23.1:3] flags=[R] seq=3109184249, ack=0, win=0 state=CLOSED rcv_nxt=3109184249, snd_una=2797527191
2021-04-16 10:23:01.367444+0900 firebaseProject[1006:67777] [tcp] tcp_input [C23.1:3] flags=[R] seq=3109184249, ack=0, win=0 state=CLOSED rcv_nxt=3109184249, snd_una=2797527191
facebook firebase success! :D 5ThQ■■■■■■■■■■■■■■
<TryFacebookFirebaseLogin>c__Iterator0:<>m__0(Task`1)
System.Threading.Tasks.<ContinueWith>c__AnonStorey0:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey2:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey1:<>m__0()
System.Threading.Tasks.Task:<immediateExecutor>m__1(Action)
System.Threading.Tasks.Task`1:RunContinuations()
System.Threading.Tasks.Task`1:TrySetResult(T)
System.Threading.Tasks.TaskCompletionSource`1:SetResult(T)
System.Threading.Tasks.<ContinueWith>c__AnonStorey0:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey2:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey1:<>m__0()
System.Threading.Tasks.Task:<immediateExecutor>m__1(Action)
System.Threading.Tasks.Task`1:RunContinuations()
System.Threading.Tasks.Task`1:TrySetResult(T)
System.Threading.Tasks.TaskCompletionSource`1:SetResult(T)
Firebase.Auth.<GetTask>c__AnonStorey0:<>m__0()
Firebase.Auth.Future_User:SWIG_CompletionDispatcher(Int32)
Firebase.AppUtil:PollCallbacks()
Firebase.Platform.FirebaseHandler:Update()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
Just in case if you wanna know. There are 1 providerID at this account
facebook.com
FirebaseAuth:DoesProvierExist(String)
<TryFacebookFirebaseLogin>c__Iterator0:<>m__0(Task`1)
System.Threading.Tasks.<ContinueWith>c__AnonStorey0:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey2:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey1:<>m__0()
System.Threading.Tasks.Task:<immediateExecutor>m__1(Action)
System.Threading.Tasks.Task`1:RunContinuations()
System.Threading.Tasks.Task`1:TrySetResult(T)
System.Threading.Tasks.TaskCompletionSource`1:SetResult(T)
System.Threading.Tasks.<ContinueWith>c__AnonStorey0:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey2:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey1:<>m__0()
System.Threading.Tasks.Task:<immediateExecutor>m__1(Action)
System.Threading.Tasks.Task`1:RunContinuations()
System.Threading.Tasks.Task`1:TrySetResult(T)
System.Threading.Tasks.TaskCompletionSource`1:SetResult(T)
Firebase.Auth.<GetTask>c__AnonStorey0:<>m__0()
Firebase.Auth.Future_User:SWIG_CompletionDispatcher(Int32)
Firebase.AppUtil:PollCallbacks()
Firebase.Platform.FirebaseHandler:Update()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
ClickButton (LogInBtn)(04/16/2021 10:23:11)
UIEventButtonClick:OnClick()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
firebase apple in
<TryAppleFirebaseLogin>c__Iterator1:MoveNext()
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
UIC_OptionPanel:_LinkMobilePlatform(E_MESSAGEBOX_CONFIRM_TYPE)
Messenger`1:Broadcast(String, T, MessengerMode)
UIC_MessageBox_Button:OnClick()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
-> applicationWillResignActive()
-> applicationDidBecomeActive()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
apple firebase success! :D 5ThQ■■■■■■■■■■■■■■
<TryAppleFirebaseLogin>c__AnonStorey3:<>m__0(ICredential)
AppleAuth.CallbackHandler:ExecutePendingCallbacks()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
Just in case if you wanna know. There are 1 providerID at this account
facebook.com
FirebaseAuth:DoesProvierExist(String)
<TryAppleFirebaseLogin>c__AnonStorey3:<>m__0(ICredential)
AppleAuth.CallbackHandler:ExecutePendingCallbacks()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
So... I found that lack of knowledge about whatever I'm doing goes very wrong...
I used apple-signin-unity by lupidan from github and mixing various tutorials that I could found on google to expect it's working. :|
Firebase blocks linking multiple accounts that already registered.
Mine just dispose previous FirebaseAuth and overwrite new one.
that is why it looked like merging accounts that actually doesn't do anything right.
I should have been more careful before I ask question.
Edit:
What was actually going on is that there's no exception at apple login.
Others have exceptions by using "ContinueWith" function but apple doesn't.
by adding it, everything works okay.

Xamarin Forms Delete Web Cache / Javascript Storage

I have an app that is using an http server to serve files to a Web View. The web viewers are caching image links which is causing broken images when their paths changes.
I can delete the web store on Android and UWP but I cannot figure out how to properly with iOS.
Android:
Android.Webkit.WebStorage.Instance.DeleteAllData();
UWP:
Windows.UI.Xaml.Controls.WebView.ClearTemporaryWebDataAsync();
I have tried the following with no luck:
NSHttpCookieStorage.SharedStorage.RemoveCookiesSinceDate(NSDate.DistantPast);
WKWebsiteDataStore.DefaultDataStore.FetchDataRecordsOfTypes(WKWebsiteDataStore.AllWebsiteDataTypes, (NSArray records) =>
{
for (nuint i = 0; i < records.Count; i++)
{
var record = records.GetItem<WKWebsiteDataRecord>(i);
WKWebsiteDataStore.DefaultDataStore.RemoveDataOfTypes(
websiteDataTypes: record.DataTypes,
date: new[] { record },
completionHandler: ()=> { });
}
for (nuint i = 0; i < records.Count; i++)
{
var record = records.GetItem<WKWebsiteDataRecord>(i);
WKWebsiteDataStore.DefaultDataStore.RemoveDataOfTypes(record.DataTypes,
new[] { record }, () => { Console.Write($"deleted: {record.DisplayName}"); });
}
});
NSUrlCache.SharedCache.RemoveAllCachedResponses();
NSUrlCache.SharedCache.DiskCapacity = 0;
NSUrlCache.SharedCache.MemoryCapacity = 0;
Found the answer at: https://gochannel.org/links/link/snapshot/640
Rewrote to Xamarin IOS
private void DeleteCachedFiles()
{
if (UIDevice.CurrentDevice.CheckSystemVersion(9, 0))
{
NSHttpCookieStorage.SharedStorage.RemoveCookiesSinceDate(NSDate.DistantPast);
WKWebsiteDataStore.DefaultDataStore.FetchDataRecordsOfTypes(WKWebsiteDataStore.AllWebsiteDataTypes, (NSArray records) =>
{
for (nuint i = 0; i < records.Count; i++)
{
var record = records.GetItem<WKWebsiteDataRecord>(i);
WKWebsiteDataStore.DefaultDataStore.RemoveDataOfTypes(record.DataTypes,
new[] { record }, () => { Console.Write($"deleted: {record.DisplayName}"); });
}
});
NSUrlCache.SharedCache.RemoveAllCachedResponses();
}
else
{
// Remove the basic cache.
NSUrlCache.SharedCache.RemoveAllCachedResponses();
var cookies = NSHttpCookieStorage.SharedStorage.Cookies;
foreach (var c in cookies)
{
NSHttpCookieStorage.SharedStorage.DeleteCookie(c);
}
}
try
{
// Clear web cache
DeleteLibraryFolderContents("Caches");
// Remove all cookies stored by the site. This includes localStorage, sessionStorage, and WebSQL/IndexedDB.
DeleteLibraryFolderContents("Cookies");
// Removes all app cache storage.
DeleteLibraryFolder("WebKit");
}
catch (Exception ex)
{
App.UnhandledException(ex, $"Error deleting cache {ex.Message}");
}
}
private void DeleteLibraryFolder(string folderName)
{
var manager = NSFileManager.DefaultManager;
var library = manager.GetUrls(NSSearchPathDirectory.LibraryDirectory, NSSearchPathDomain.User).First();
var dir = Path.Combine(library.Path, folderName);
manager.Remove(dir, out NSError error);
if (error != null)
{
App.UnhandledException(new Exception(error.Description), error.Description);
}
}
private void DeleteLibraryFolderContents(string folderName)
{
var manager = NSFileManager.DefaultManager;
var library = manager.GetUrls(NSSearchPathDirectory.LibraryDirectory, NSSearchPathDomain.User).First();
var dir = Path.Combine(library.Path, folderName);
var contents = manager.GetDirectoryContent(dir, out NSError error);
if (error != null)
{
App.UnhandledException(new Exception(error.Description), error.Description);
}
foreach (var c in contents)
{
try
{
manager.Remove(Path.Combine(dir, c), out NSError errorRemove);
if (errorRemove != null)
{
App.UnhandledException(new Exception(error.Description), error.Description);
}
}
catch (Exception ex)
{
App.UnhandledException(ex, $"Error deleting folder contents: {folderName}{Environment.NewLine}{ex.Message}");
}
}
}

Resources