You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Firebase谷歌登录,实现Android视图认证前屏蔽功能

实现基于Firebase谷歌登录的AuthenticatedActivity认证拦截

嗨,我来帮你完成这个AuthenticatedActivity的认证逻辑,确保只有已登录用户能访问受保护的视图,未认证用户会被拦截并引导登录。

1. 完善AuthenticatedActivity的核心认证逻辑

首先我们补全基类的代码,添加FirebaseAuth状态监听、谷歌登录配置,以及用户状态变化的处理逻辑:

public class AuthenticatedActivity extends AppCompatActivity {
    private final static String TAG = "AuthenticatedActivity";
    private static final int RC_SIGN_IN = 123;
    protected FirebaseUser firebaseUser;
    private FirebaseAuth auth;
    private FirebaseAuth.AuthStateListener authStateListener;
    private GoogleSignInClient googleSignInClient;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        // 初始化FirebaseAuth实例
        auth = FirebaseAuth.getInstance();
        
        // 配置谷歌登录选项(记得替换成你的web client id)
        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestIdToken(getString(R.string.default_web_client_id))
                .requestEmail()
                .build();
        googleSignInClient = GoogleSignIn.getClient(this, gso);
        
        // 初始化认证状态监听器,实时监听用户登录/登出状态
        authStateListener = firebaseAuth -> {
            firebaseUser = firebaseAuth.getCurrentUser();
            if (firebaseUser != null) {
                // 用户已认证,显示页面内容
                showAuthenticatedContent();
            } else {
                // 用户未认证,屏蔽内容并引导登录
                blockUnauthenticatedAccess();
            }
        };
    }

    @Override
    protected void onStart() {
        super.onStart();
        // 注册监听器,页面启动时立即检查认证状态
        auth.addAuthStateListener(authStateListener);
    }

    @Override
    protected void onStop() {
        super.onStop();
        // 注销监听器,避免内存泄漏
        if (authStateListener != null) {
            auth.removeAuthStateListener(authStateListener);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        
        // 处理谷歌登录返回的结果
        if (requestCode == RC_SIGN_IN) {
            Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
            try {
                // 谷歌登录成功,获取凭证完成Firebase认证
                GoogleSignInAccount account = task.getResult(ApiException.class);
                firebaseAuthWithGoogle(account);
            } catch (ApiException e) {
                Log.w(TAG, "Google sign in failed", e);
                Toast.makeText(this, "登录失败,请重试", Toast.LENGTH_SHORT).show();
            }
        }
    }

    // 用谷歌凭证完成Firebase认证
    private void firebaseAuthWithGoogle(GoogleSignInAccount acct) {
        Log.d(TAG, "firebaseAuthWithGoogle:" + acct.getId());

        AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
        auth.signInWithCredential(credential)
                .addOnCompleteListener(this, task -> {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "signInWithCredential:success");
                        firebaseUser = auth.getCurrentUser();
                    } else {
                        Log.w(TAG, "signInWithCredential:failure", task.getException());
                        Toast.makeText(AuthenticatedActivity.this, "认证失败", Toast.LENGTH_SHORT).show();
                    }
                });
    }

    // 已认证用户显示页面内容的方法
    protected void showAuthenticatedContent() {
        // 默认显示Activity的根视图,子类可按需重写
        View contentView = getContentView();
        if (contentView != null) {
            contentView.setVisibility(View.VISIBLE);
        }
    }

    // 未认证用户的拦截处理
    private void blockUnauthenticatedAccess() {
        // 隐藏页面核心内容
        View contentView = getContentView();
        if (contentView != null) {
            contentView.setVisibility(View.GONE);
        }
        // 自动启动谷歌登录流程
        startGoogleSignIn();
        // 也可以替换成显示自定义登录提示布局,让用户手动触发登录
        // loginPromptView.setVisibility(View.VISIBLE);
    }

    // 启动谷歌登录意图
    private void startGoogleSignIn() {
        Intent signInIntent = googleSignInClient.getSignInIntent();
        startActivityForResult(signInIntent, RC_SIGN_IN);
    }

    // 子类可重写此方法,指定需要屏蔽/显示的内容视图
    protected View getContentView() {
        return findViewById(android.R.id.content);
    }
}

2. 子类继承基类的使用方式

你的受保护页面只需要继承这个基类,正常编写自己的布局和业务逻辑即可,基类会自动处理认证拦截:

public class ProfileActivity extends AuthenticatedActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_profile);
        
        // 这里编写仅已登录用户可访问的逻辑,比如展示用户信息
        if (firebaseUser != null) {
            TextView userName = findViewById(R.id.tv_user_name);
            userName.setText(firebaseUser.getDisplayName());
        }
    }

    // 如果你的内容视图不是默认根布局,可重写此方法指定目标视图
    @Override
    protected View getContentView() {
        return findViewById(R.id.profile_content_container);
    }
}

3. 关键细节说明

  • 实时状态监听:使用AuthStateListener可以实时响应用户登录/登出操作,比如用户在其他页面登出,当前受保护页面会自动触发拦截逻辑。
  • 视图屏蔽逻辑:通过控制视图的显示/隐藏,确保未登录用户完全看不到敏感内容,而不是简单跳转页面。
  • 谷歌登录配置:记得在Firebase控制台获取default_web_client_id,并在项目的strings.xml中配置,否则登录会失败。
  • 内存防护:在onStop()中注销监听器,避免Activity销毁后监听器仍然持有引用导致内存泄漏。

4. 可选优化方向

  • 添加自定义登录提示布局,代替自动启动登录,给用户更友好的引导。
  • 增加登录失败的重试逻辑,比如添加重试按钮。
  • 在拦截状态下显示加载动画,避免用户重复触发登录操作。

内容的提问来源于stack exchange,提问作者Filip

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:54:32