import com.google.android.gms.auth.api.Auth;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.auth.api.signin.GoogleSignInResult;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.SignInButton;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthCredential;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.auth.GetTokenResult;
import com.google.firebase.auth.GoogleAuthProvider;
import com.google.firebase.auth.PhoneAuthCredential;
import com.google.firebase.auth.PhoneAuthProvider;
import com.google.firebase.FirebaseException;
import com.google.firebase.auth.FirebaseAuthInvalidCredentialsException;
import com.google.firebase.FirebaseTooManyRequestsException;
import android.app.Activity;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import anywheresoftware.b4a.AbsObjectWrapper;
import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.IOnActivityResult;
import anywheresoftware.b4a.BA.DependsOn;
import anywheresoftware.b4a.BA.Events;
import anywheresoftware.b4a.BA.Hide;
import anywheresoftware.b4a.BA.Version;
import anywheresoftware.b4a.BA.ActivityObject;
import anywheresoftware.b4a.BA.ShortName;
import java.util.concurrent.TimeUnit;
// ,"firebase-auth-10.2.6.aar","play-services-auth-10.2.6.aar","play-services-auth-base-10.2.6.aar"
@ShortName("FirebaseAuthPhone")
@DependsOn(values={"com.google.firebase:firebase-auth", "com.google.android.gms:play-services-auth"})
@Events(values={"SignedIn (User As FirebaseUser)", "TokenAvailable (User As FirebaseUser, Success As Boolean, TokenId As String)"})
@Version(0.01f)
// @ActivityObject
public class FirebaseAuthWrapper implements ConnectionCallbacks, OnConnectionFailedListener {
@Hide
public GoogleApiClient googleClient;
@Hide
public FirebaseAuth auth;
private IOnActivityResult ion;
private boolean signOut;
private String eventName;
private PhoneAuthProvider.ForceResendingToken mResendToken;
private PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks;
// private BA ba;
/**
* Initializes the object. The SignedIn event will be raised if there is already a signed in user.
*/
public void Initialize(final BA ba, String EventName) {
// this.ba= ba;
mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
@Override
public void onVerificationCompleted(PhoneAuthCredential credential) {
// This callback will be invoked in two situations:
// 1 - Instant verification. In some cases the phone number can be instantly
// verified without needing to send or enter a verification code.
// 2 - Auto-retrieval. On some devices Google Play services can automatically
// detect the incoming verification SMS and perform verificaiton without
// user action.
// Log.d(TAG, "onVerificationCompleted:" + credential);
// [START_EXCLUDE silent]
// mVerificationInProgress = false;
// [END_EXCLUDE]
BA.Log("onVerificationCompleted");
// [START_EXCLUDE silent]
// Update the UI and attempt sign in with the phone credential
// updateUI(STATE_VERIFY_SUCCESS, credential);
// [END_EXCLUDE]
// signInWithPhoneAuthCredential(credential);
}
@Override
public void onVerificationFailed(FirebaseException e) {
// This callback is invoked in an invalid request for verification is made,
// for instance if the the phone number format is not valid.
BA.Log("onVerificationFailed"+e.getMessage());
// [START_EXCLUDE silent]
// [END_EXCLUDE]
if (e instanceof FirebaseAuthInvalidCredentialsException) {
// Invalid request
// [START_EXCLUDE]
BA.Log("FirebaseAuthInvalidCredentialsException");
// [END_EXCLUDE]
} else if (e instanceof FirebaseTooManyRequestsException) {
// The SMS quota for the project has been exceeded
// [START_EXCLUDE]
BA.Log("FirebaseTooManyRequestsException");
// [END_EXCLUDE]
}
// Show a message and update the UI
// [START_EXCLUDE]
// [END_EXCLUDE]
}
@Override
public void onCodeSent(String verificationId,
PhoneAuthProvider.ForceResendingToken token) {
// The SMS verification code has been sent to the provided phone number, we
// now need to ask the user to enter the code and then construct a credential
// by combining the code with a verification ID.
// Save verification ID and resending token so we can use them later
BA.Log("onCodeSent");
// [START_EXCLUDE]
// Update UI
// [END_EXCLUDE]
}
};
// [END phone_auth_callbacks]
auth = FirebaseAuth.getInstance();
eventName = EventName.toLowerCase(BA.cul);
auth.addAuthStateListener(new FirebaseAuth.AuthStateListener() {
@Override
public void onAuthStateChanged(FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null)
ba.raiseEventFromDifferentThread(FirebaseAuthWrapper.this, null, 0, eventName + "_signedin", false, new Object[] {AbsObjectWrapper.ConvertToWrapper(new FirebaseUserWrapper(), user)});
}
});
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(BA.applicationContext.getResources().getString(GetResourceId("string", "default_web_client_id")))
.requestEmail()
.build();
googleClient = new GoogleApiClient.Builder(ba.context)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso).addConnectionCallbacks(this).addOnConnectionFailedListener(this)
.build();
googleClient.connect();
}
public void startPhoneNumberVerification(final BA ba,String phoneNumber,Long timeout) {
final Activity act = ba.sharedProcessBA.activityBA.get().activity;
// [START start_phone_auth]
PhoneAuthProvider.getInstance().verifyPhoneNumber(
phoneNumber, // Phone number to verify
timeout, // Timeout duration
TimeUnit.SECONDS, // Unit of timeout
act, // Activity (for callback binding)
mCallbacks); // OnVerificationStateChangedCallbacks
// [END start_phone_auth]
// mVerificationInProgress = true;
}
/**
* Returns the current signed in user. Returns an uninitialized object if there is no user.
*/
public FirebaseUserWrapper getCurrentUser() {
return (FirebaseUserWrapper) AbsObjectWrapper.ConvertToWrapper(new FirebaseUserWrapper(), auth.getCurrentUser());
}
@Hide
@Override
public void onConnected(Bundle arg0) {
if (signOut) {
Auth.GoogleSignInApi.signOut(googleClient);
}
signOut = false;
}
@Hide
@Override
public void onConnectionSuspended(int arg0) {
}
@Hide
@Override
public void onConnectionFailed(ConnectionResult arg0) {
BA.Log("connection failed.");
}
/**
* Sign outs from Firebase and Google.
*/
public void SignOutFromGoogle() {
auth.signOut();
if (googleClient.isConnected()) {
Auth.GoogleSignInApi.signOut(googleClient);
}
else {
signOut = true;
googleClient.connect();
}
}
/**
* Start the sign in process.
*/
public void SignInWithGoogle(final BA ba) {
final Activity act = ba.sharedProcessBA.activityBA.get().activity;
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(googleClient);
ion = new IOnActivityResult() {
@Override
public void ResultArrived(int resultCode, Intent intent) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(intent);
if (result.isSuccess()) {
GoogleSignInAccount account = result.getSignInAccount();
firebaseAuthWithGoogle(act, account);
}
}
};
ba.startActivityForResult(ion, signInIntent);
}
/**
* Retrieves the token id. This token can be sent to your backend server. The server can use it to verify the user.
*The TokenAvailable event will be raised in the current module.
*/
public void GetUserTokenId(final BA ba, final FirebaseUserWrapper User, boolean ForceRefresh) {
User.getObject().getToken(ForceRefresh).addOnSuccessListener(new OnSuccessListener<GetTokenResult>() {
@Override
public void onSuccess(GetTokenResult arg0) {
ba.raiseEventFromDifferentThread(FirebaseAuthWrapper.this, null, 0, eventName + "_tokenavailable", false, new Object[] {User, true, arg0.getToken()});
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception arg0) {
ba.raiseEventFromDifferentThread(FirebaseAuthWrapper.this, null, 0, eventName + "_tokenavailable", false, new Object[] {User, false, ""});
}
});
}
private void firebaseAuthWithGoogle(Activity act, GoogleSignInAccount acct) {
AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
auth.signInWithCredential(credential)
.addOnCompleteListener(act, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(Task<AuthResult> task) {
}
});
}
private int GetResourceId(String Type, String Name) {
return BA.applicationContext.getResources().getIdentifier(Name, Type, BA.packageName);
}
@ShortName("FirebaseUser")
public static class FirebaseUserWrapper extends AbsObjectWrapper<FirebaseUser> {
public String getEmail() {
return getObject().getEmail();
}
public String getDisplayName() {
return getObject().getDisplayName();
}
public String getUid() {
return getObject().getUid();
}
public String getPhotoUrl() {
return getObject().getPhotoUrl() == null ? "" : getObject().getPhotoUrl().toString();
}
}
}