Subhojit Halder
Subhojit Halder

Reputation: 170

ClassCastExceptions while authenticate with Firebase defined in a separate class

I've separated the Google Sign-in and FirebaseAuth in a class. Everything was working fine but suddenly I'm getting ClassCastExceptions.

java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=700, result=-1, data=Intent { (has extras) }} to activity {com.androidcitizen.easycomputernetworks/com.androidcitizen.easycomputernetworks.activity.MainActivity}: java.lang.ClassCastException: com.androidcitizen.easycomputernetworks.FirebaseAuthWithGoogle cannot be cast to java.util.concurrent.Executor
        at android.app.ActivityThread.deliverResults(ActivityThread.java:4423)
        at android.app.ActivityThread.handleSendResult(ActivityThread.java:4465)
        at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:49)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1831)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:201)
        at android.app.ActivityThread.main(ActivityThread.java:6810)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
     Caused by: java.lang.ClassCastException: com.androidcitizen.easycomputernetworks.FirebaseAuthWithGoogle cannot be cast to java.util.concurrent.Executor
        at com.androidcitizen.easycomputernetworks.FirebaseAuthWithGoogle.getFirebaseAuthWithGoogle(FirebaseAuthWithGoogle.java:49)
        at com.androidcitizen.easycomputernetworks.activity.MainActivity.onActivityResult(MainActivity.java:311)
        at android.app.Activity.dispatchActivityResult(Activity.java:7590)

Here I've a SignIn Button to start Signin process from MainActivity.java class.

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btnGoogleSignIn = findViewById(R.id.btn_google_signin);
        btnFacebookLogin = findViewById(R.id.fb_login_button);
        btnSIgnOut = findViewById(R.id.btn_sign_out);
        btnStartLearning = findViewById(R.id.btn_start_learning);
        txtUserName = findViewById(R.id.txt_user_name);
        imgUserPhoto = findViewById(R.id.img_user_photo);

        btnGoogleSignIn.setOnClickListener(this);
        btnSIgnOut.setOnClickListener(this);

        btnStartLearning.setEnabled(false);
        btnStartLearning.setAlpha(0.5f);

        mSignInWithGoogle = new SignInWithGoogle(this, this);
        mAuthWithGoogle = new FirebaseAuthWithGoogle(this);

        Log.d(TAG, "onCreate end!");
    }

 @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_google_signin:
                Log.d(TAG, "btn_google_signin clicked!");
                mSignInWithGoogle.signIn();
                break;
            case R.id.btn_sign_out:
                Log.d(TAG, "btn_sign_out clicked!");
                mSignInWithGoogle.signOut(mAuthWithGoogle.getmAuth());
                break;
                default:
                    Log.d("MainActivity", "default");
        }
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        //callbackManager.onActivityResult(requestCode, resultCode, data);
        // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
        if (requestCode == RC_SIGN_IN) {
            Log.d(TAG, "requestCode: " + RC_SIGN_IN);
            Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
            try {
                // Google Sign In was successful, authenticate with Firebase
                final GoogleSignInAccount account = task.getResult(ApiException.class);
                Log.d(TAG, "DisplayName: " + account.getDisplayName());
                mAuthWithGoogle.getFirebaseAuthWithGoogle(account);      // Suspected line in logcat

                // firebaseAuthWithGoogle(account);
            } catch (ApiException e) {
                // Google Sign In failed, update UI appropriately
                Log.w(TAG, "Google sign in failed", e);
                // ...
            }
        }
    }

SignInWithGoogle.java class

public class SignInWithGoogle {
    private static final String mTAG = "SignInWithGoogle.java";
    public static final int RC_GOOGLE_SIGN_IN = 700;

    private Context mContext;
    private Activity mActivity;
    private GoogleSignInClient mGoogleSignInClient;


    public SignInWithGoogle(Context context, Activity activity) {
        this.mContext = context;
        this.mActivity = activity;
        Log.d(mTAG, "SignInWithGoogle Constructor!");
    }

    public GoogleSignInClient getGoogleSignInClient() {        //First Calling this to get GoogleSignInClient
        Log.d(mTAG, "getGoogleSignInClient() - instance!");
        // Configure Google Sign In
        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestIdToken(mContext.getResources().getString(R.string.default_web_client_id))
                .requestEmail()
                .build();

        mGoogleSignInClient = GoogleSignIn.getClient(mContext, gso);
        return mGoogleSignInClient;
    }

    public void signOut(FirebaseAuth mAuth) {
        //FirebaseAuth.getInstance().signOut();
        mAuth.signOut();
        getGoogleSignInClient().signOut().addOnCompleteListener((Executor) this, new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                Log.d(mTAG, "Google Sign Out: " + "success!");
                //updateSignUI(null);

            }
        });
    }

    public void signIn() {
        Log.d(mTAG, "Google Sign In Processing ..");
        Intent signInIntent = getGoogleSignInClient().getSignInIntent();
        mActivity.startActivityForResult(signInIntent, RC_GOOGLE_SIGN_IN);
    }
}

FirebaseAuthWithGoogle.java

public class FirebaseAuthWithGoogle {
    private static final String mTAG = "FirebaseAuthWithGoogle";
    private Context context;
    private FirebaseAuth mAuth;
    private OnFirebaseAuthListener authListener;

    public interface OnFirebaseAuthListener{
        void updateSignedUI(FirebaseUser user);
    }

    public FirebaseAuthWithGoogle(Context context) {
        Log.d(mTAG, "Constructor with Context!");
        this.context = context;
        this.authListener = (OnFirebaseAuthListener) context;
        mAuth = FirebaseAuth.getInstance();
        Log.d(mTAG, "Constructor with Context!!");
    }

    public FirebaseAuth getmAuth() {
        Log.d(mTAG, "getmAuth()");
        return mAuth;
    }

    public void getFirebaseAuthWithGoogle(GoogleSignInAccount acct) {
        Log.d(mTAG, "getFirebaseAuthWithGoogle() - Account ID: " + acct.getId());
        AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
        Log.d(mTAG, "getFirebaseAuthWithGoogle() - credential: " + credential);
        mAuth.signInWithCredential(credential)                   // <<<<<< this line throwing the exceptions
                .addOnCompleteListener((Executor) this, new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        if (task.isSuccessful()) {
                            // Sign in success, update UI with the signed-in user's information
                            Log.d(mTAG, "firebaseAuthWithGoogle: success");
                            FirebaseUser user = mAuth.getCurrentUser();
                            authListener.updateSignedUI(user);
                        } else {
                            // If sign in fails, display a message to the user.
                            Log.w(mTAG, "signInWithCredential:failure", task.getException());
                            //Toast.makeText(MainActivity.this, "Authentication Failed.", Toast.LENGTH_SHORT).show();
                            authListener.updateSignedUI(null);
                        }
                        // ...
                    }
                });
    }
}

SO i'm getting the issue on ActivityResult method. And in this FirebaseAuthWithGoogle.java class at line with mAuth.signInWithCredential(credential) ... throws the ClassCastExceptions. How can I fix this?

Upvotes: 0

Views: 746

Answers (3)

Umar Farooq
Umar Farooq

Reputation: 489

I was getting the same error when authenticating with Firebase. I just happen to replace 'this' with 'getActivity()' which handled the exception very well.

replace 'this' with 'getActivity()'

Upvotes: 0

Kasasira
Kasasira

Reputation: 403

This is what @CKing is practically saying:

  1. Create a class called FirebaseAuthWithGoogle that implements Executor interface:

    class FirebaseAuthWithGoogle implements Executor {
        @Override
        public void execute(@NonNull Runnable r) {
            r.run();
        }
    }
    
  2. Now pass an instance of FirebaseAuthWithGoogle class to the addOnCompletionListener method:

    FirebaseAuth.getInstance().signInWithCredential(googleAuthCredential)
        .addOnCompleteListener( new FirebaseAuthWithGoogle(), new OnCompleteListener<AuthResult>() 
        {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {
                if(task.isSuccessful()){
                    // Your code here
                }else {
                    Log.e(TAG,task.getException().getMessage());
                }
            }
        });
    
  3. Run your app and don't forget to smile because the Exception has been handled.

Upvotes: 0

Chetan Kinger
Chetan Kinger

Reputation: 15212

I'm getting the issue on ActivityResult method. And in this FirebaseAuthWithGoogle.java class at line with mAuth.signInWithCredential (credential) ... throws the ClassCastExceptions

The root cause of the ClassCastException is that the following line of code is trying to cast an instance ofFirebaseAuthWithGoogle (referred to by this) into an Executor :

mAuth.signInWithCredential(credential)                   
                .addOnCompleteListener((Executor) this, new OnCompleteListener<AuthResult>()

Since FirebaseAuthWithGoogle is clearly not an instance of type Executor, a ClasCastException is naturally thrown. To fix this issue, either have FirebaseAuthWithGoogle implement the Executor interface and override the execute method or create a new class that implements Executor and pass an instance of that class to the addOnCompletionListener method.

Upvotes: 2

Related Questions