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

React Native Expo独立应用Google登录返回dismissed的原因排查

Expo独立应用Google登录返回dismissed的解决方法

针对你遇到的Expo Go中登录正常、独立应用打包后Google登录弹窗关闭返回dismissed的问题,按以下步骤排查解决:

  • 核对Android应用的SHA-1指纹
    独立应用的签名指纹和Expo Go完全不同,必须把打包用的指纹添加到Google开发者控制台的对应Android客户端中:

    • 若用Expo默认签名,执行命令:expo fetch:android:hashes 获取SHA-1和SHA-256指纹
    • 若用自定义签名文件,用keytool生成指纹:keytool -list -v -keystore your-keystore-file.jks
      把获取到的指纹添加到Google控制台的Android应用配置里。
  • 确认Client ID配置正确
    代码中androidClientId必须是Google控制台中Android类型的客户端ID,不能混用Web类型的ID;独立应用可以移除expoClientId(该ID仅用于Expo Go环境),只保留androidClientId和webClientId(如果需要支持Web登录)。

  • 添加scheme配置
    在app.json或app.config.js中添加scheme字段,比如:

    {
      "expo": {
        "scheme": "yourappscheme"
      }
    }
    

    然后在Google控制台的Android客户端授权重定向URI中添加:yourappscheme://oauthredirect

  • 调整promptAsync参数
    独立应用是原生环境,不需要useProxy: true(该参数用于Expo Go/Web的代理跳转),可以简化promptAsync调用:

    promptAsync({ showInRecents: true })
    
  • 修改后的代码示例

    import * as Google from 'expo-auth-session/providers/google';
    import * as WebBrowser from 'expo-web-browser';
    import React from "react";
    import { View, Text, Button, StatusBar } from 'react-native';
    
    interface User {
      name: string,
      email: string,
      picture: string,
    }
    
    export default function App() {
      const [accessToken, setAccessToken] = React.useState<string | null>(null);
      const [userInfo, setUserInfo] = React.useState<User | null>(null);
      const [txt, setTxt] = React.useState("");
    
      WebBrowser.maybeCompleteAuthSession();
    
      const [request, response, promptAsync] = Google.useAuthRequest({
        androidClientId: '正确的Android客户端ID',
        webClientId: '正确的Web客户端ID'
      });
    
      React.useEffect(() => {
        setTxt(response?.type || '')
        if(response?.type === "success") {
          setAccessToken(response.authentication!.accessToken);
        }
      }, [response])
    
      const getUserInfo = async () => {
        if (!accessToken) return;
        const userInfoResponse = await fetch("https://www.googleapis.com/userinfo/v2/me", {
          headers: { Authorization: `Bearer ${accessToken}` }
        });
        const userInfo = await userInfoResponse.json();
        setUserInfo(userInfo);
      }
    
      const showUserInfo = () => {
        if (!userInfo) return null;
        return (
          <View>
            <Text>姓名: {userInfo.name}</Text>
            <Text>邮箱: {userInfo.email}</Text>
            <Text>头像: {userInfo.picture}</Text>
          </View>
        )
      }
    
      return (
        <View style={{ flex:1, justifyContent:'center', alignItems:'center', gap:16 }}>
          <Text>{txt}</Text>
          {showUserInfo()}
          <Text>{accessToken}</Text>
          <Button 
            title={accessToken ? "获取用户信息" : "登录"} 
            onPress={accessToken ? getUserInfo : () => promptAsync({ showInRecents: true })} 
          />
          <StatusBar style="auto" />
        </View>
      );
    }
    

内容的提问来源于stack exchange,提问作者K. Gero

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 16:45:47